sproutcoresproutcore-views

Binding a view's layout property to an Object controller


I've recently begun working in Sproutcore, which seems to be a really good solution for client side web app development. However, the documentation isn't as thorough or concise as I'd like, so I am struggling with a few things.

Specifically, I'm trying to bind the layout property of one of my views to an object. I've managed this to an extent, in that when the view is rendered it uses the properties from the object, but the problem I'm having is that when the object is updated, the view's dimensions don't change. However, if the change is persistent and I reload the page, it uses the new values.

Is there some sort of limitation in binding layout properties so that they dynamically update, or do I have the wrong approach here?


Solution

  • I'm not sure this approach will work. Controllers are not supposed to have anything to do with a view's properties; controllers are ONLY supposed to proxy objects.

    One alternative you might want to consider is using the adjust method defined on the SC.View class. You can have your view observe a property on the model it represents, and then in the observer call

    this.adjust('height', 30); // or whatever

    I think adjust can also be used like

    this.adjust({
        height: 10,
        width: 20,...
    })
    

    without knowing more about what you are trying to do, its hard to say more.

    MORE DETAIL

    Ok, so one thing about Sproutcore is you need to be careful to not get in the way of the runloop. Unfortunately, there isn't much documentation on this. What I have learned is that you wan't observers to observe things in in their scope only. So here is an outline of what you want to do.

    SC.View.extend({
       layout: {...}, // initial properties
    
       // binding to the text field that adjusting depends on, NOT on 
       // this view's content
       outsidePropertyBinding: "binding.to.textField", 
    
       outsidePropertyDidChange: function(){
           var outsideProperty = this.get('outsideProperty');
           this.adjust({
              // as shown before
           })
       }.observes('outsideProperty') // <-- this is how you create an observer
    
    });
    

    What I've shown here is how to adjust based on something that is changing outside of this view. I created

    1) A binding to the outside property, which SC updates for you
    2) An observer on the bound property, that fires as soon as the value is set, and adjusts the view. The observer is observing a property in the view, not out of the view.

    Note that if your view is bound to some content, and its a property on that content itself that changes, then you would do it slightly differently. You wouldn't need the binding to the outside property, you could instead just observe '*content.relevantproperty'. The * before content tells the observer that the content object itself might change (if the views content object can change).