ViewModel 2 - A new level of simplicity

Wait, I thought you had no control over the helper. In that case you can just call the method directly:

Template.greeting.viewmodel({
  firstName() {
    return this.templateInstance.state.get("firstName");
  },
  anotherMethod() {
    console.log( this.firstName() )
  }
});

Ah, I know I could move the code from the helper in to the viewmodel.

But if I had to keep the code inside of Template.greeting.helper, is there no way I could access that from a viewmodel (without moving it)?

You donā€™t have to use Template.greeting.helper because a VM method is a helper.

Sorry, my questions are probably confusing the situation a bit more, but basically the ā€˜Template.greeting.helperā€™ is controlled by the package, Iā€™m able to extend it with a viewmodel, but still need to access the code contained in the Template.greeting.helper (if possible).

Itā€™s seeming like in this case it might be easier to not use viewmodel on this page.

Thanks for the prompt responses! And apologies for any confusion!

Back to my original response, I donā€™t think you can access a helper outside the markup if you canā€™t modify the way the helper is defined. This isnā€™t a VM issue, youā€™re going to run into the same problem without VM.

Okay, thank you very much!

My Blaze is definitely rusty so ask the question in this forum, someone might know the answer: ā€œHow can I access a helper method from code (I have the template instance) if I canā€™t modify the way the helper is defined (itā€™s in a 3rd party package)?ā€

One way:

Helper map for a template can be accessed from within a viewmodel at this.templateInstance.view.template.__helpers.

So, you can get in your example firstName helper:


 // get function
let firstNameFunction = this.templateInstance.view.template.__helpers.get('firstName');

// invoke function
let firstName = this.templateInstance.view.template.__helpers.get('firstName')();
1 Like

@manuel, I was wondering - is there a way to add a generic property to all viewmodels? Similar to a mixin only without declaring a mixin in every viewmodel?

Update to v6.2.0. I havenā€™t updated the docs yet but it works the same as the React version: https://viewmodel.org/#AdvancedGlobal

2 Likes

@manuel, Iā€™ve just stumbled upon https://atmospherejs.com/manuel/viewmodel-explorerā€¦
Is this some kind of debug tool? how do I use it? I kinda overlooked it in the docs (is it mentionned??)

1 Like

Yes it is a debug tool. Cool one to be clear.
It pretty much smillar to redux store view, except, it allows full control over viewmodel during development.
Such as setting inputs, data, props, firing events and etc. When you include it in your app, look for new UI el.

1 Like

I donā€™t remember the last time I used VM Explorer for Blaze so I donā€™t know if it even works anymore. My guess is that it doesnā€™t work for VM Blaze v2 (but of course Iā€™ve been wrong before). The React version works similarly and you can see how it works at https://viewmodel.org by clicking on the paper plane icon:

May I ask what does the future of ViewModel for Blaze look like? Grim, aging gracefully or keep evolving? :slight_smile:

One way to look at VM for Blaze is as being part of the old Meteor stack. Blaze itself is pretty much frozen and so is VM for Blaze. VM is pretty much feature complete so itā€™s just a matter of fixing eventual bugs. So ā€œaging gracefullyā€ is the most appropriate term :slight_smile:

1 Like

Btw, Manuel - does VM feature set (by any chance) include a way to profile what triggered reactive update to vm property or caused vm method to rerun? Iā€™d like to log that data for development purposesā€¦

Thatā€™s a tough one. I donā€™t have a good answer. Itā€™s technically possible for VM to log when properties are changed and also when functions rerun due to a change in their dependencies, but Iā€™m not going to code that in any time soon.

Chromeā€™s async option helps sometimes (https://www.html5rocks.com/en/tutorials/developertools/async-call-stack/).

Could you nudge me in the right direction? Maybe Iā€™d monkeypatch VM to do just thatā€¦

You can do a quick and dirty monkey patch by updating the loadProperties method to wrap the functions in a another that logs when the function is about to run:

  @loadProperties = (toLoad, container) ->
    loadObj = (obj) ->
      for key, value of obj when not ViewModel.properties[key]
        if ViewModel.reserved[key]
          throw new Error "Can't use reserved word '" + key + "' as a view model property."
        else
          if _.isFunction(value)
            # we don't care, just take the new function
            container[key] = value
            
            # Instead do something like:
            #
            # wrapped = (args...) ->
            #   console.log "About to run: " + key
            #   value args
            #
            # And then:
            # container[key] = wrapped

And also funProp:

    funProp = (value) ->
      if arguments.length
        if _value isnt value
          changeValue = ->
            # console.log "Going to change " + _value + " to " + value

It will probably be a good idea to pass the property name to makeReactiveProperty to log it too. Right now funProps are anonymous.

Hope it helps.

1 Like

Incidentally, @manuel, I was thinking about a scenario that I could not use viewmodel forā€¦

Imagine a mortgage calculator, where number of years affects the monthly payment, AND the monthly payment might be set by the user to a lower value, and expect that the # of years would changeā€¦ In this case, which field is the raw one, and which is the derived?

Whatā€™s solved this for me is that redux ā€˜smearsā€™ the state out over time. I write a reducer that changes the state underneath, depending on which quantity the user wants to adjust. Then I have a pure-function renderer which, minimally, updates the DOM based on which parts have changed.

Itā€™s been interesting to work more with Reactā€¦ I was just looking back to see if I wanted to use viewmodel for my current use case, and thought itā€™d be worth an ask if you saw a way to do this in VM. (perhaps by grabbing events on derived properties, and turning them into changes on the ā€˜leafā€™ propertiesā€¦)

cheers,
Dean