2

In Aurelia we have the ability to dynamically compose viewmodels and views using the <compose> element. We can also supply an object of data via model.bind which is then accessible via the activate method of the provided viewmodel.

My question is, what conditions trigger a change event on the provided model data? If I change a property on the object I provide, will my activate method which gets this object as the first parameter see the change? Or does the entire object need to be replaced to trigger a change?

Dwayne Charrington
  • 6,524
  • 7
  • 41
  • 63
  • I wrote an example and did some tests and the changes were reflected everytime. Maybe you should provide some code and your excact use case, so it is easier to help you – kabaehr Apr 25 '16 at 09:04
  • The thing is this is not for any existing application or code. The question is more high level for documentation purposes. The binding system in Aurelia, what gets observed, how and when is one of those unknown components of the framework. The Aurelia documentation does very little to explain when things like this. Because I don't have a use-case right now, I have no code. So if a property on an object changes in your tests, the value was updated? Perhaps it is being passed by reference? – Dwayne Charrington Apr 25 '16 at 09:37
  • Arrays are updated in method such as push, pop, etc. as described in this answer http://stackoverflow.com/questions/36394399/how-to-force-binding-re-evaluate-or-re-rendering-in-aurelia/36409924#36409924. Properties are updated when their value changes. The `activate` method is called once, before view is activated – Fabio Apr 25 '16 at 14:14

1 Answers1

3

The activate(model) gets called once when the model is bound to the view model. When the model attributes change, those changes will be reflected in the composed view model because the model is a reference, not a copy.

For example, say I have a view / view model that is a target for a route as follows (this example is not a perfectly clean example because I was experimenting with other things as well, but it should be clear enough):

View: This view creates two sections separated by an <hr>. The top just displays the model.message for each view. The bottom creates a <compose> for each view.

<template>
  <div repeat.for="view of openViews">
    <p>${view.model.message}</p>
  </div>
  <hr>
  <div repeat.for="view of openViews">
    <compose view-model.bind="$parent.getViewFromType(view)" model.bind="view.model">
    </compose>
  </div>
</template>

View Model: note that the openViews is at a global scope. This is so that if we navigate away from the route and then return to the route, any changes made to the view.model will be retained. If the model was on the ZenStudio object, the object gets destroyed and recreated when the route moves away and returns to this view and therefore would lose the data.

var openViews = [
  { viewType: "", model: { message: "View 1"}},
  { viewType: "", model: { message: "View 2"}},
  { viewType: "", model: { message: "View 3"}}
];

export class ZenStudio {
  constructor() {
  }

  created() {
  }

  get openViews() {
    return openViews;
  }

  getViewFromType(view) {
    // TOOD Load plugins and use the views defined by plugins
    return "./views/editor-view";
  }
}

The editor-view view and view-model are as follows:

<template>
  <h1>${model.message}</h1>
  <form>
    <input type="text" value.bind="model.message">
  </form>
</template>

View-model:

export class EditorView {
  constructor() {
  }

  created(owningView, thisView) {
    this.view = thisView;
    this.parentView = owningView;
  }

  activate(model) {
    // Keep track of this model
    this.model = model;
  }
}

You'll see that the ZenStudio view is displaying the same model.message as the EditorView. When the user edits the value of the message inside the <input>, the values correctly change in the top level view, as well as within the corresponding <compose> view.

While I don't have an example, if you added another item to openViews list then that would add another sub view and another line in the top level view displaying the new message. The repeat.for listens to the additions and subtractions made to the list and correctly creates / removes the composed elements.

Hopefully that answers your question.

Tony Richards
  • 391
  • 3
  • 5