Wednesday, April 20, 2011

Sproutcore: StackedView is stacking content

If you developed in Sproutcore you used for sure the ListView component. And of course you’ve encountered the long lines problem that it gets cut and you wondered how can you make the lines to have height accordingly with the content inside. Don’t hit your head of the walls anymore, Sproutcore has StackedView component which makes all that magic.

Lets see if it does that:
First we check the documentation for StackedView component
“A StackedView is a CollectionView that expects its content to use static
 layout to stack vertically.  This type of collection view is not designed
 for use with large size collections, but it can be very useful for
 collections with complex displays and variable heights such as comments or
 small notification queues...
 This view makes no attempt to size or position your child views.
 It assumes you are using StaticLayout for your child views...”
and more on that we see that it extends the SC.CollectionView. The next steps is:

- to look at the SC.StaticContentView’s content property:
“The HTML content you wish to display. This will be inserted directly into the DOM, so ensure that any user-generated content has been escaped …  @type String”
and keep that in mind;

- to look at the SC.CollectionView:
“... The view will create instances of  exampleView to render the array ...”
and further more on exampleView which is SC.ListItemView type and continue with SC.ListItemView:

“The content object the list item will display... @type SC.Object”

So we want our exampleView to be SC.StaticContentView type, in fact this is the recommendation for StackedView. But what will happen with content, it will be String or SC.Object and how the components will manage that?

If we write our code to extract some information from content:
testStackedView: SC.StackedView.design({
  contentBinding: 'arrangedObjects from our controller with data',
  selectionBinding: 'selection from our controller with data',
  layout: { top: 0, bottom: 0, left: 0, right: 0},
  exampleView: SC.StaticContentView.design({
    staticHtml: function() {
      var content = this.get('content'), html = '';

      if (!SC.none(content)) {
        html += '' + content.get('someProperty') + '';
      }
      return html;
    }.property('content').cacheable(),
    contentBinding: 'staticHtml'
  })
...
we will get errors like that
Uncaught TypeError: Object [object DOMWindow] has no method 'getPath'
and that’s because our content in fact is content from exampleView which is string.
We need to overwrite the render method like this to make things work:
testStackedView: SC.StackedView.design({
  contentBinding: 'arrangedObjects from our controller with data',
  selectionBinding: 'selection from our controller with data',
  layout: { top: 0, bottom: 0, left: 0, right: 0},
  exampleView: SC.StaticContentView.design({
    render: function(context, firstTime) {
      var content = this.get('content'), html = '';
  
      if (!SC.none(content)) {
        html += '' + content.get('someProperty') + '';
        context.push(html);
      }
    }
  })
...
Now we see the difference and our StackedView now works just fine.

That was my piece of code.

No comments:

Post a Comment