These are chat archives for canjs/canjs

21st
Jun 2017
Viktor Busko
@Lighttree
Jun 21 2017 12:13
I think that documentation way better than it was couple of years ago, a lot of good examples, great done.js "In-depth guide", that covers most of questions.
But maybe it makes sense to add more "generic" things, but required for any application, things like:
session handling
authentication / authorization
internationalization
etc.
Pedro Mendes
@pmgmendes
Jun 21 2017 15:51
@justinbmeyer Thanks a lot for your feedback. i had to make a fair amount of changes in the component because the this.entry.children has being read in other derived properties. But yeah, the value being just read w/i the if() provides a nice workaround.
Pedro Mendes
@pmgmendes
Jun 21 2017 16:08

Hi all. Can someone clarify if the can-stream/can-define-stream can help speeding up the stache rendering of an list? By speeding up I'm referring to make the operation less CPU intensive. Consider the following code where the entryItems can resolve to 1000 items.

var Item = DefineMap.extend({
   id: "string",
   children: {
      type: "any",
      get() {
        return SubItem.getList({parent: this.id});
      }
   }
});

# component viewmodel
var CatalogVM = DefineMap.extend({
  active: "boolean",
  entry: Item,
  entryItems: {
    get(lastSetVal, resolve) {
      if (this.active) {
        let children = this.entry.children;
        children.then(data => {
          resolve(data);
        }, error => {
          resolve([]);
        });
      }
      return [];
    }
  }
});

# componet template
{{#each entryItems}}
  <item {data}="this" ... >
{{/each}}

If I render each item as just a <li> its rather fast but because its an custom element with a few associated bindings (and other stuff) this kind of operation makes the application not responsive during the rendering time.

Justin Meyer
@justinbmeyer
Jun 21 2017 16:17
streams will not help you here
Gira Minus
@gKreator
Jun 21 2017 16:18
I think using a DefineList and rendering it as a list is fastet
Justin Meyer
@justinbmeyer
Jun 21 2017 16:18
@pmgmendes though I would really like to see this app and analyze its performance :-)
I've been wanting to spend time making components a bit faster
do you need diffing on entryItems?
meaning do single items get added / removed
or when entryItems changes, its a whole new set of items, with none of the same items previously
if that's the case {{#entryItems}} can be a bit faster
streams won't help because they don't eliminate what I expect to be the slow part ... all the bindings (we still bind to the streams)
one thing that might help a bit 25% or so ... is 3.9
which should make far fewer computes, and more fast Observations
Btw, @/all here's the credit-card code: http://jsbin.com/qiwaned/edit?html,js,output
fixed
Pedro Mendes
@pmgmendes
Jun 21 2017 16:22
@justinbmeyer While there can be entryItems being add or removed it's a edge case. Most of the times the entryItems are fetch just once and immediately rendered without any change in the list size.
Even tough if an item within the list have some of its properties changed I do want that change to reflect. But it is because of this scenario that we're configuring the relevant can-connect behaviors to store that item instance avoiding re-fetching the list again --> This is working as expected. The item name changes and I see that being reflect in the rendered 1000 item list immediately.
Gira Minus
@gKreator
Jun 21 2017 16:29
Why dont you use infinite scroll? Im sure you cant see all the items at once
Set a bool on the items and only set it to true when they are in the viewport.
Do it every 100 items or so like pagination
Justin Meyer
@justinbmeyer
Jun 21 2017 16:38
@pmgmendes another option would be to make something similar to the fall-through-cache logic
essentially, return a resolved promise right away ... but .push() items onto it 100 at a time
in little intervals
( use #each if you do this )
Pedro Mendes
@pmgmendes
Jun 21 2017 16:52
@justinbmeyer That makes sense. I'm gonna give it a try.
@gKreator Yes, that's correct. The only thing that might block me of using that approach is the fact we've have a filter input that just toggles the visibility of the <item> elements based on the filter term match. Not having a <item> render means that it won't be shown even if it matches the filter term.
Gira Minus
@gKreator
Jun 21 2017 17:03
Your filter can overwrite it. Justins suggestion will be harder to implement with this. Imo
Justin Meyer
@justinbmeyer
Jun 21 2017 17:07
@pmgmendes could you change the service layer to support NDJSON?
what browsers do you support?
and how much control over the backend do you have?
Pedro Mendes
@pmgmendes
Jun 21 2017 17:08
@gKreator I guess not because the filter just toggles visibility (display: block|none). Even if it takes 10 seconds (!) to render the 1000 items and the user tries to filter those items before the list is completely rendered I still expect the items rendered after the filter input to be shown or not according the match.
I have no problem delaying the rendering a bit. What I do need to avoid is blocking the main thread for large periods of time e.g. > 500 ms.
Yeswanth Raghav T
@tyraghav
Jun 21 2017 17:11
I am calling or importing a object of can.component.extend (which has a viewmodel) into a three controllers of different screens
When I navigate between the screens each controller is loading
But for each screen i think separate model object is created
When I make a onclick event for this object two or three calls are happening due to this redundancy
Can anyone help me with this please
Justin Meyer
@justinbmeyer
Jun 21 2017 17:13
@tyraghav a new instance of the component's ViewModel is created for each <custom-element>
so yes, a separate ViewModel object is created
well, I'm not sure about the 3 calls
can you write up some pseudo code in a forum post?
Yeswanth Raghav T
@tyraghav
Jun 21 2017 17:14
Ok
Oh
Pedro Mendes
@pmgmendes
Jun 21 2017 17:15
@justinbmeyer That would be nice.. but unfortunately our service layer is unable to streaming anything.
Just Chrome for now.
We've the control. But it will not happen in the time frame I need (yesterday)..
your code would look something like:
getListData: function(set){
  self._getHydrateList(set, function(list){
    // make sure to keep this in the store while we are getting the data
    self.addListReference(list, set);
    // get the real data
    baseConnection.getListData(set).then(function(raw){
      var i = 0;
      while(i < raw.data.length){
        list.push.apply(this, raw.slice(i, i+100)
        i += 100
      }
      self.deleteListReference(list, set);
    })
  });
  return Promise.resolve({data: []})
}
Justin Meyer
@justinbmeyer
Jun 21 2017 17:23
if you build this, please share it
Yeswanth Raghav T
@tyraghav
Jun 21 2017 17:34
I am stealing the can.component extend into three can.control.extend as follows
Steal('can','commoncomponentModel.js',function(can,Idselect){
Var r=can.control.extend(.............);
Return r;
}
Yeswanth Raghav T
@tyraghav
Jun 21 2017 17:46
Please help
Mohamed Cherif Bouchelaghem
@cherifGsoul
Jun 21 2017 18:12
@tyraghav can.Control.extend with a capital C
Yeswanth Raghav T
@tyraghav
Jun 21 2017 19:06
I used capital C in the code
I have found the issue and mentioned it above
Please help
Gira Minus
@gKreator
Jun 21 2017 19:56
Any error logs?
Yeswanth Raghav T
@tyraghav
Jun 21 2017 20:51
It is not throwing error but data is not getting loaded into stache
brent-g
@brent-g
Jun 21 2017 21:02
Hey guys, I was wondering if someone can shed some light on an issue i'm having with routing. Is this the appropriate place to inquire for help?
Gira Minus
@gKreator
Jun 21 2017 21:09
Yup
brent-g
@brent-g
Jun 21 2017 21:27

awesome! so right now I have my app.js file like this. ```const AppViewModel = Map.extend({
define: {
section: {
set: function(newVal) {
return newVal || 'home';
}
},
pagePromise: {
get: function() {
var self = this;
var section = this.attr('section');
var route = section;
return Page.getList({ route: route, expand: 'all'}).then(function(pages) {
if(pages && pages.length > 0) {
var page = pages[0];
self.attr('page', page);
return page;
}
});
}
},
page: {
value: null,
serialize: false
}
}
});

stache.registerHelper("pageComponent", function(options) {
var page = options.context.attr('page');
var template = 'Loading..';

if(page) {
    template = '<' + page.attr('tag') + ' {component}="page" />';
}

return stache(template)(this, options.helpers, options.nodeList);

});

route(':section', { section: null });
``` which loads components dynamically through a helper. The section property determines which component to load. When I change the route from inside a loaded component via a function on the viewmodel using this.attr('%root').attr('newpage1'); the url/route changes momentarily to localhost:8080/newpage1 like expected but then after a second of loading refreshes back to the home screen. Why is this?

Sorry I cant quite get the formatting correct.
brent-g
@brent-g
Jun 21 2017 21:35
also, if i change the url to localhost:8080/newpage1 it stays on the appropriate page
brent-g
@brent-g
Jun 21 2017 22:12
anyone got any ideas?
harmowbray
@harmowbray
Jun 21 2017 22:28
hello everyone. i am not very experienced with can.js :worried: I see in CSS that someone wrote can-value="partner.advertisingId.xboxone". how do you get that same value with javascript? sorry if this is a simple question
Pedro Mendes
@pmgmendes
Jun 21 2017 23:03
@justinbmeyer I'm struggling a bit to build something similar to your sample code.
In the getListData example there's two lists list and raw and I understand whenever the entries from data are pushed to list at the end of the execution stack (after wrapping it in a setTimeout) wherever list is bound the newly pushed entries are rendered.
In my code the flow is happening w/i derived prop entryItems compute after active change so I'm not sure to what collection I should be pushing to.
And how about resolve? What should I do with it?
var CatalogVM = DefineMap.extend({
  active: "boolean",
  entry: Item,
  entryItems: {
    get(lastSetVal, resolve) {
      if (this.active) {
        let children = this.entry.children;
        children.then(data => {
          let i = 0;
          while(i < data.length){
            // lastSetVal ???
            ????.push.apply(this, data.slice(i, i+100);
            i += 100;
          }
        }, error => {
          resolve([]);
        });
      }
      return [];
    }
  }
});