Binding Enyo.Collection subkind to DataGridList

edited November 2014 in Newbie Questions
Hi,

I'm trying to write an app that is going to pull off some data off a web service and display it as a grid of images.
The code that i've got so far:
enyo.kind({
the JSON returned by service looks like this:
image

The datagridlist definition looks like this:
enyo.kind({
	name: "KTV.CategoryViewPanel",
	kind: "KTV.Panel",
	components: [  {kind:"moon.Item", name: "start", content: "-----Start-----"},
	               {kind: "moon.Button", content: "Halt!", ontap: "halt"},
	               {kind: "moon.DataGridList", fit:true, name: "resultList", minWidth: 250, minHeight: 300, components: [
                 			{kind: "moon.GridListImageItem", imageSizing: "cover", useSubCaption:false, centered:false, bindings: [
             				{from: ".model.title", to:".caption"},
             				{from: ".model.thumbnail", to:".source"}
                     			]}
                 		]},
                  {kind:"moon.Item", name: "end", content: "-----End-----"},                  
               ],
    bindings: [ 
        {from:".categories", to: ".$.resultList.collection"}
    ],
    create: function() {
    	this.inherited(arguments);
        this.set("categories",this.model);
    	this.categories=this.model;
    	this.categories.fetch();
    	//i try it in different ways
    	this.$.resultList.refresh();
    	},
The above mess (which is a result of 12+ hours of fun with debugger) generates something like this:
image

If i try to bind that same collection via DataRepeater, all works perfectly
components: [  {kind:"moon.Item", name: "start", content: "-----Start-----"},
	               {kind: "moon.Button", content: "Halt!", ontap: "halt"},
	               {kind: "enyo.DataRepeater", name:"textdata", components:[
                       {kind:"moon.Item", components:[
                                                      {name:"categoryName"},
                                                      {name:"thumbnail"}],
                                                      bindings:[
                                                                {from:".model.name", to:".$.categoryName.content"},
                                    	           				{from:".model.thumbnail", to:".$.thumbnail.content"}
                                                                 ]}
                   ]},
                  {kind:"moon.Item", name: "end", content: "-----End-----"},                  
               ],
    bindings: [ 
        {from:".categories", to: ".$.textdata.collection"}
    ],
Literally at a stage when i'm ready to bang my head against the wall.

One thing i'm suspecting is that collection is populated via ajax call, which happens after rendering of the page, and that confuses the datagridlist....

Any help/pointers appreciated.

Comments

  • In this part:
     bindings: [ 
            {from:".categories", to: ".$.resultList.collection"}
        ],
        create: function() {
        	this.inherited(arguments);
            this.set("categories",this.model);
        	this.categories=this.model;
        	this.categories.fetch();
        	//i try it in different ways
        	this.$.resultList.refresh();
        	},
    "categories" is your collection, but in the create, you set it to a model, and your doing it 2 different ways.

    this.set("categories",this.model); This will trigger the binding and set the collection to whatever this.model is

    this.categories=this.model;, this sets this.categories directly with this.model, and it won't trigger any bindings.

    So if this.model is just a model, and not a collection, the datalist will fail.


  • Chris,
    Thanks for your comment!
    As i mentioned, i tried to do it in a large number ways, none of them seems to be working.
    Last iteration is where i set this.categories via
    this.set("categories",this.model)

    the model passed to the form is the actual collection (i understand i may be doing something terribly wrong by doing so, as i do not fully embrace the MVC concept), however that was one of the ways i found i can pass on data from mainview form to this form that i'm trying to display.
    The passed `model` is a collection, as can be seen by this debugger output:
    image

    Even with that, the result is the same

    The collection i am passing sits in the mainview
    enyo.kind({
            name: "KTV.MainView",
            kind: "enyo.View",
            handlers: {
                    onShowPanel: "showPanel",
                    onGoHome: "goHome",
                    onShowPopup: "showPopup",
                    onLogin:"executeLogin"
            },
            components: [
                 		{name: "sadTrombone", kind: "moon.Popup", components: [
                 		                                                       {layoutKind: "enyo.FittableColumnsLayout", components: [
                 		                                                                                                               {fit: true, name: "MessageBox", content: ""},
                 		                                                                                                               {kind: "moon.Button", name: "Finebutton", content: "Fine", ontap: "hidePopup"}
                 		                                                                                                               ]}
                		                                                       ]},
                        {name: "panels", kind: "moon.Panels", pattern: "activity", components:[{name: "panel", kind: "KTV.Panel"}]},
                		{name: "FileIOReadService",kind: "FileIOService",method: "read",onComplete: "readServiceResponse"},
                		{name: "Logindata", kind:"KTV.LoginData"},
                		{name: "ChannelRecord", kind:"KTV.CategoryCollection"}
                    ],       
    i am then passing this collection to the form via the following two calls
    this.bubble("onShowPanel", {name: "CategoryView", model: this.$.ChannelRecord});
    
    and then
    showPanel: function(inSender, inEvent) {
                    var panelKind = "KTV." + inEvent.name + "Panel";
                    var model = inEvent.model;
                    this.$.panels.popPanels(1);
                    this.$.panels.pushPanel({kind: panelKind, model: model});
                    return true;
            }        
    
    current constructor for the KTV.CategoryViewPanel looks like this: with still not much love. The objects inside the collection do not appear to be data-bound (they appear as simple objects, no attributes or anything) if looking through debugger)
     create: function() {
        	this.inherited(arguments);
        	this.set("categories",this.model);
        	this.categories.fetch();
        	},

    Also - should binding be done or refreshed when collection finishes the AJAX request, or it is done automatically when collection is updated?

    Would love to share this in jsfiddle, but can't unfortunately, as the service i'm developing for requires to perform a login to get to this step.

    The most mystifying thing is that it works perfectly if i use DataRepeater and Moon.Item to store the data.
  • a bound collection should auto update when the data changes.
    It is a big problem that your records aren't being turned into actual models. That's probably why its not working.

    just noticed you are defining your collection as a component. I've never used them that way, so i'm not sure if it will work.

    Usually, i would declare the collection in the create function like:
     create: function() {
        	this.inherited(arguments);
        	this.set("ChannelRecord", new KTV.CategoryCollection());
        	},
    And then you'd reference is via this.ChannelRecord
  • Chris,
    Thanks for a suggestion.
    Now collection creation looks like that:
    this.set("ChannelRecord", new KTV.CategoryCollection());
    in the main.js at constructor
    then
    this.bubble("onShowPanel", {name: "CategoryView", model: this.ChannelRecord});
    
    (removed the .$.)

    still same result. records not turning into models.

    At some iteration...somewhere between 3 and 4 am (meaning i don't remember what i did) i got those records to become models, however that didn't help either. I think i was playing with the $ in the .model.name binding by putting it in random places.
  • update: managed to get it all on to jsfiddle:

    jsfiddle.net/sheree_boman/c9b17cva/13/

    The problem is now that on jsfiddle it doesn't like the fetch() requests for some reason
  • Another update:
    managed to get it "somewhat" working on JSFiddle, however it's not the "same thing" as running it in the emulator, as collection immediately creates a model
    http://jsfiddle.net/sheree_boman/c9b17cva/
    on the contrary when run in emulator, it creates records :S
    confused, unhappy, spent 16+ hours on this already and still can't understand what's not right :(
  • edited November 2014
    Last update: somehow magicallyl the thing started to work. And again - no idea what was changed. Current code
    
    enyo.kind({
    	name: "KTV.CategoryViewPanel",
        kind: "KTV.Panel",
    	components: [ {kind: "moon.DataGridList", name: "resultList", fit:true, minwidth:500, minheight:500, spacing: 100, components: [
                     			{kind: "moon.GridListImageItem", useCaption: true, ontap:"channellist", imageSizing:"cover", bindings: [
                 				{from: ".model.name", to:".caption"},
                 				{from: ".model.thumbnail", to:".source"}
                         			]}
                     		]}
                      
                   ],
        bindings: [ 
            {from:".categories", to: ".$.resultList.collection"}
        ],
        create: function() {
        	this.inherited(arguments);
            this.set("categories",this.model);
            this.categories.fetch();
        },
    Many thanks to chrisvanhooser for helping with suggestions
  • agragr
    edited November 2014
    Maybe the answer is in bindings: {from: ".model.name", to:".caption"},
    the name and thumbnail is a second level (sub-property). And bidings for subproperties doesn't work for enyo.js v2.3.0 or v.2.4.0. It works only for latests build v.2.5.0.3
    I also have the same problem with data repeter.


    this code tests this bug:
    
    
    enyo.kind({
    	name : "testKind",
    	kind : "enyo.Application",
    	view : "ProgramsView",
    
    });
    
    
    enyo.kind({
    	name : "ProgramsView",
    	kind: "enyo.Control",
    	published: {
    		mymodel: {
    				kind: "enyo.Model",
    				id: "default id", 
    				text: "default content"
    			}, 
    		
    			test_id: "test id",
    			test_name: "Artem test name",
    		
    	},
    	
    	create: function(){
    		this.inherited(arguments);
    		var defaultModel = {
    				kind: "enyo.Model",
    				id: "my  id", 
    				text: "my content"
    			};
    		debugger;
    		this.set("mymodel", defaultModel);
    		
    	},
    	rendered: function(){
    		this.inherited(arguments);
    		
    		
    	},
    	
    	components: [
            {name: "modelContentId", content: "no mo"},
            {name: "modelContent", content: "no m"},	    
             {name: "text_name", content: "no m",}
    	],
    	
    	bindings: [
    	           //{from: ".model.id", to: ".$.modelContentId.content"},
    	           {from: ".mymodel", to: ".$.modelContent.content", transform: function(val) {
    	        	   debugger;                   
    	                return val.text;  // bindings  like  .model.text modelContent.Id dont't work in v2.4
    	            }},
                    {from: ".mymodel", to: ".$.modelContentId.content", transform: function(val) {
    	        	   debugger;                   
    	                return val.id;  // bindings  like  .model.id -> modelContent.Id dont't work in v2.4
    	            }},
    	           {from: ".test_name", to: ".$.text_name.content", transform: function(val) {
    	        	   debugger;
    	                return val;
    	            }}
    	],
    	
    	buttonTapped: function(inSender, inEvent) {
    		debugger;
    		app.$.detailsController.Index();
    	},
    });
    
            
    new testKind().renderInto(document.body);
    
Sign In or Register to comment.