These are chat archives for canjs/canjs

24th
Mar 2016
Thomas Sieverding
@Bajix
Mar 24 2016 01:49
How do I read/write to the root scope w/in a component
Thomas Sieverding
@Bajix
Mar 24 2016 02:22
How does %root work?
dylanrtt
@dylanrtt
Mar 24 2016 03:55
@Bajix %root is just a child map of all components' viewmodels, so you can do this.attr('%root.foo') or this.attr('%root.foo', bar)
Thomas Sieverding
@Bajix
Mar 24 2016 03:56
dylanrtt
@dylanrtt
Mar 24 2016 03:56
are you asking how to use it in a template?
Thomas Sieverding
@Bajix
Mar 24 2016 03:57
yes
My impression was that I’d be able to do <foo *bar> … {{*bar.someProp}} ..</foo>
I’m a little confused though, as I had expected %root.bar to be set as the exported vm
dylanrtt
@dylanrtt
Mar 24 2016 04:00
scope lookups to component viewmodels don't fall-through to %root if that's what you are thinking
whereas scope in the template does (not sure if I said that right)
Thomas Sieverding
@Bajix
Mar 24 2016 04:00
I see - I had thought %root was the template scope
dylanrtt
@dylanrtt
Mar 24 2016 04:01
This message was deleted
Thomas Sieverding
@Bajix
Mar 24 2016 04:01
%root is the top most ref?
So if you’re doing leakScope: false, then child components would have %root === the vm of the parent
dylanrtt
@dylanrtt
Mar 24 2016 04:02
yes, the top most ref
shouldn't matter with leakScope:whatever
Thomas Sieverding
@Bajix
Mar 24 2016 04:03
That’s inconsistent w/ the docs. *bar should be the vm itself
dylanrtt
@dylanrtt
Mar 24 2016 04:03
oh sorry my bad, I don't usually use that syntax
Thomas Sieverding
@Bajix
Mar 24 2016 04:03
Well, leakScope would just mean that it’s now the top most ref
So if I had <my-app *app><my-service>{{>views/index}}</my-service></my-app>, shouldn’t I be able to do {{*app.foo}} within index?
dylanrtt
@dylanrtt
Mar 24 2016 04:09
I don't think so. *app would only be available within the outer template. They are not passed down
Thomas Sieverding
@Bajix
Mar 24 2016 04:09
Even if my-service uses leakScope: true?
dylanrtt
@dylanrtt
Mar 24 2016 04:10
honestly, I'm not totally sure but I don't think reference scope is inherited in partials. not sure why the component's leakScope would matter
Thomas Sieverding
@Bajix
Mar 24 2016 04:11
Hmm. I had been treating it like a shortcut to my root scope, but I guess that’s innaccurate
dylanrtt
@dylanrtt
Mar 24 2016 04:12
what does %root have to do with your latest example?
Thomas Sieverding
@Bajix
Mar 24 2016 04:12
leakScope affects %root, and I had though that * was intended to manipulate root
W/ what I’m working on, I have a top level container component, and I was trying to export it’s vm as *ui, then wrap a partial in a service component, and access *ui within that partial
dylanrtt
@dylanrtt
Mar 24 2016 04:14
I believe %root was added initially for ssr. *ref bindings were added so you could easily share values between components without setting up an initial parent value to which those components would bind
Thomas Sieverding
@Bajix
Mar 24 2016 04:14
Yea, so it’s really in there for sibling interactions
dylanrtt
@dylanrtt
Mar 24 2016 04:14
exactly
Thomas Sieverding
@Bajix
Mar 24 2016 04:15
My misconception was thinking that it was a shortcut to the parent most can.view.Scope
It’s not partial friendly for that reason
dylanrtt
@dylanrtt
Mar 24 2016 04:15
sibling interactions where siblings is defined as anything in the template
if you replace the partial with a component, you could pass the *app into it
Thomas Sieverding
@Bajix
Mar 24 2016 04:18
Well, not sure that would work in my case
<chat-service {_id}="{_id}" {^is-loading}="./isLoading" {^is-enabled}="./isEnabled" {(is-expanded)}="./isExpanded" {is-focused}="./isFocused" {(is-opened)}="./isOpened" {isMobile}="./isMobile">
  {{>chat/views/core}}
</chat-service>
There we go
That’s my container’s template, and I’d like the container’s vm to be accessible by my partial as ui
dylanrtt
@dylanrtt
Mar 24 2016 04:20
Is there a reason you don't just make chat/views/core the template of <chat-service>? Is this a flexibility thing?
Thomas Sieverding
@Bajix
Mar 24 2016 04:21
Yup. The service adds some things to the scope, and ties in web sockets
I have other areas in which I want to use the service to mediate my state
dylanrtt
@dylanrtt
Mar 24 2016 04:22
yeah you may have to make a component for each partial then
if you want to use ref scope
Thomas Sieverding
@Bajix
Mar 24 2016 04:22
How would a component fit into play here?
dylanrtt
@dylanrtt
Mar 24 2016 04:22
I imagine the child-to-parent bindings would work in the partial
Thomas Sieverding
@Bajix
Mar 24 2016 04:23
They do
I was having issues earlier with doing {ui}=“./"
dylanrtt
@dylanrtt
Mar 24 2016 04:25
<chat-service {^is-loading}="*isLoading">
  <chat-view view="core" is-loading="*isLoading"></chat-view>
</chat-service>
Thomas Sieverding
@Bajix
Mar 24 2016 04:25
I just want a reference key so that other partials can look up the scope tree w/out needing to know how far it’s nested
My use case is to do stuff like ($click)=“ui.attr(‘userMenu’, false)"
dylanrtt
@dylanrtt
Mar 24 2016 04:27
with isLoading available in <chat-view>, it can load the partial and the partial will see it
Thomas Sieverding
@Bajix
Mar 24 2016 04:28
It would be cool if you could set component’s templates
<chat-service template=“chat/views/core”></chat-service>
That’d be the dream
dylanrtt
@dylanrtt
Mar 24 2016 04:30
yeah, I was thinking of a dynamic partial, which might have build consequences if done incorreclty
Thomas Sieverding
@Bajix
Mar 24 2016 04:31
I don’t think your example does anything differently to the view scope than what’s already accomplished with how I’m already loading the partial
I can do {{isLoading}} just fine
dylanrtt
@dylanrtt
Mar 24 2016 04:32
I was just thinking maybe you wanted to use references scope
but what you are doing is fine
Thomas Sieverding
@Bajix
Mar 24 2016 04:32
But the template loaded by the chat-view component wouldn’t be able to read that references scope?
dylanrtt
@dylanrtt
Mar 24 2016 04:33
it would not, so you would have to pass everything in, which is inconvenient
Thomas Sieverding
@Bajix
Mar 24 2016 04:33
It doesn’t appear to afford my any new capabilities, but maybe I’m missing something
Well, you can just use leakScope instead of passing everything in
that way it’ll lookup keys in the parent scope anyway
dylanrtt
@dylanrtt
Mar 24 2016 04:34
I was just showing a way to do references scope since you were originally talking about it
Thomas Sieverding
@Bajix
Mar 24 2016 04:34
Why doesn’t this work? {ui}=“./“ Shouldn’t that set the ui prop of my chat-service vm to the container’s vm?
<chat-service {ui}="./">
  {{>chat/views/core}}
</chat-service>
I don’t get why this wouldn’t simply set chat-service vm’s ui prop to the vm of my container
dylanrtt
@dylanrtt
Mar 24 2016 04:36
does just . work? what exactly is the container? if you nested that in another component in the template, the parent component will be the "container"
Thomas Sieverding
@Bajix
Mar 24 2016 04:37
<chat-container> is a component w/ some ui state in the vm
It’s just a wrapper
dylanrtt
@dylanrtt
Mar 24 2016 04:38
<chat-container>
    <foo-bar>
        <chat-service {ui}="./">
          {{>chat/views/core}}
        </chat-service>
    </foo-bar>
</chat-container>
would use the <foo-bar> vm
Thomas Sieverding
@Bajix
Mar 24 2016 04:38
Hmm yea . works
I guess I was too clever for my own good there
<chat-container>
  <chat-service {ui}="./">
    {{>chat/views/core}}
  </chat-service>
</chat-container>
That’s what I had, only I just rewrote it to make chat-container always have a template, and now I’m using auto-render
dylanrtt
@dylanrtt
Mar 24 2016 04:44
looks like a bug that ./ doesn't work. appears to start breaking in 2.3.14
Thomas Sieverding
@Bajix
Mar 24 2016 04:46
Yea, the other extremely weird issue I have is that System.buildStatic affects scope lookup
So now I’m using {ui}=“.” and my sub templates can read/write from it properly
But, if I use System.buildStatic instead of System.bundle then my scope tree breaks
So… that’s the other reason why I got confused =/
I really want to deliver my app as a single SFX file
Thomas Sieverding
@Bajix
Mar 24 2016 04:52
There are a couple weird scoping bugs that I’ve found… like you can’t use can-import in conjunction with can.view.attr
dylanrtt
@dylanrtt
Mar 24 2016 04:54
ok I see where the ./ issue is - easy fix
@Bajix do you mean using a custom attribute on the <can-import> tag?
or using can-import to import a custom attribute
Thomas Sieverding
@Bajix
Mar 24 2016 04:58
define([
  'can',
  'tagger'
], function( can ) {
  var Tagger = can.Control({
    init: function( el, options ) {
      this.list = options.list;
      this.refresh(this.list);
    },
    refresh: function(list) {
      var items = list.attr();
      this.element.tagsinput('removeAll');
      while (items && items.length) {
        this.element.tagsinput('add', items.shift());
      }
    },
    ' itemAdded': function( el, ev ) {
      if (!~this.list.indexOf(ev.item)) {
        this.list.push(ev.item);
      }
    },
    ' itemRemoved': function( el, ev ) {
      var index = this.list.indexOf(ev.item);
      if (~index) {
        this.list.splice(index, 1);
      }
    },
    '{list} change': function( list ) {
      this.refresh(list);
    }
  });

  can.view.attr('tagger', function( el, attrData ) {
    var key = el.getAttribute('tagger'),
      list = attrData.scope.compute(key)();

    new Tagger(el, {
      list: list
    });
  });
});
If I wanted to do <can-import from=“tagger/directive”></can-import>, that wouldn’t work
But if I load it before my template, it does work
IMO that’s a huge flaw w/ can.view.attr, and makes it really difficult to use them
dylanrtt
@dylanrtt
Mar 24 2016 05:00
are you intentionally using the async version of can-import?
Thomas Sieverding
@Bajix
Mar 24 2016 05:00
No
dylanrtt
@dylanrtt
Mar 24 2016 05:01
<can-import from=“tagger/directive” /> should work if you load it in the template where you use the tagger attribute
Thomas Sieverding
@Bajix
Mar 24 2016 05:01
I was having issues w/ that
dylanrtt
@dylanrtt
Mar 24 2016 05:02
with the self-closing tag or the other way?
Thomas Sieverding
@Bajix
Mar 24 2016 05:02
But, I may have had other issues, I’ll follow up w/ an issue once I confirm with fresh eyes
The other way
It didn’t have any contents
dylanrtt
@dylanrtt
Mar 24 2016 05:03
even without contents, the open/close way will be async which you probably don't want
Thomas Sieverding
@Bajix
Mar 24 2016 05:03
Ah
dylanrtt
@dylanrtt
Mar 24 2016 05:03
you could still do it that way if you waited for the import to resolve with stache bindings
Thomas Sieverding
@Bajix
Mar 24 2016 05:04
It shouldn’t matter though, I’m using a modified stache plugin that makes imports & sub templates direct dependencies
dylanrtt
@dylanrtt
Mar 24 2016 05:17
well maybe the plugin isn't working as intended. Does changing it to the synchronous import style work?
Thomas Sieverding
@Bajix
Mar 24 2016 05:17
Oh I solved the SFX issue ^^
It was a case of the SFX messing up a document.body reference, which was breaking all of my popups/tooltips that are based on detaching document fragments and appending to body
@dylanrtt The stache plugin doesn’t work w/ SystemJS out of the box. It’s more than just not working as intended haha
I’ll check out synchronous importing in the morning and let you know
I think you’re right though, It was definitely bundling instead of making it a dependency
Sami Pietilä
@smiper
Mar 24 2016 08:12
Something wrong with the CanJS version 2.3.21? I get a cb() never called -error on NPM install. All is fine on 2.3.20, though.
Windows && node -v => 5.9.1 && npm -v => 3.7.3
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 24 2016 08:29
@smiper is not npm problem?
Sami Pietilä
@smiper
Mar 24 2016 08:47
I think i might be related to a particular dependency CanJS uses in 2.3.21 version? As i said the 2.3.20 works installs just fine for me.
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 24 2016 08:47
Yes I tried it
thank you smiper
can you open an issue?
Sami Pietilä
@smiper
Mar 24 2016 08:49
Sure, but right now I'm kinda in a hurry at work :) I might be able to write a short description of the issue
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 24 2016 08:49
np :)
Sami Pietilä
@smiper
Mar 24 2016 08:52
canjs/canjs#2340 sorry if this is a little sloppy :worried:
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 24 2016 09:15
@smiper it's fine :)
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 24 2016 09:21
@smiper the problem is with the version of NPM @pYr0x and I have the same problem there's an other issue already submited canjs/canjs#2335
Sami Pietilä
@smiper
Mar 24 2016 09:27
Ok, thanks. Should I remove my issue, then? I think the npm 3.7.3 is the latest stable version at least in their website. Annoying :smile:
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 24 2016 09:28
no it's closed
thank you :)
Sami Pietilä
@smiper
Mar 24 2016 09:28
Thank you :smile:
Christopher Oliphant
@RALifeCoach
Mar 24 2016 18:19
Hey folks, I have a brand new issue. I am building a table of about 100 rows. Each row is being built using canjs but not yet added to the page. This was existing code so I measured the timings from before and after. (Before uses jQuery tmpl.) Before runs at .4 seconds to build the 100 rows, with CanJS it runs at 3.9 seconds.
Why so slow?
More importantly, what can I do to speed it up?
Christopher Oliphant
@RALifeCoach
Mar 24 2016 18:25
@cherifGsoul any ideas?
Christopher Oliphant
@RALifeCoach
Mar 24 2016 19:02
Each row is fairly complex with many conditions being checked. some conditions were sufficiently complex to require a method in the viewModel that returned true or false.
Alexis Abril
@alexisabril
Mar 24 2016 19:05
@RALifeCoach The crux is the bindings. Basically, for each {{item}} in each cell you have, we’re setting up various bindings to make sure it’s live updatable, which takes time
using jQuery or just drawing the values directly is naturally faster, since you’re removing the live binding feature
What I’ve done in the past, is identify cells or areas of the grid/page that don’t need to be live updated
I usually have a helper that will return the value without setting up any bindings
{{#items}}{{raw ’name’}}{{/items}} for example
David Luecke
@daffl
Mar 24 2016 19:08
@smiper I just published a new version 2.3.22 which should fix your issue
Alexis Abril
@alexisabril
Mar 24 2016 19:08
a couple notes on the above, {{#items}} maybe faster than {{#each items}} in this case
{{raw …}} is a helper that would just return the value of options.context[key], where key is the argument passed in
notice, I’m using options.context[key] instead of options.context.attr(key)
the call to .attr() is what sets up the binding, whereas foo.bar would just return the value(speed!)
those are a couple notes off hand, but I’m sure I’ve forgotten something
Christopher Oliphant
@RALifeCoach
Mar 24 2016 19:09
I will try that and see what happens
Kevin Phillips
@phillipskevin
Mar 24 2016 19:19
also, if you have things like ($click)=“” within your rows, that will set up a handler for every row
that’s where the events object and event delegation help like you were asking about yesterday @RALifeCoach
Marshall Thompson
@marshallswain
Mar 24 2016 19:24
@RALifeCoach That definitely seems high for 100 rows. I tested one of my apps with 109 rows and it's well under a second using then {{#each}} helper and with live binding enabled on all data. 1000 rows is only taking a few seconds. Of course, you might have more complex behavior that's needed, but you might consider running a few tests where you remove a column and compare. I ran into a similar situation a few weeks ago. I had created a can.view.attr that was causing a huge time waste. I refactored the can.view.attr and it made all the difference.
Thomas Sieverding
@Bajix
Mar 24 2016 19:27
@RALifeCoach Another approach is to split up work accross multiple animation frames.
define([
  'can',
  'config',
  'message/model'
], function( can, config, Message ) {
  can.Component.extend({
    tag: 'message-mediator',
    leakScope: false,
    viewModel: {
      define: {
        messages: {
          value: Array,
          Type: Message.List,
          set: function( list ) {
            list.attr('comparator', 'createdAt');
            return list;
          }
        },
        buffer: {
          value: Array,
          Type: Message.List,
          set: function( list ) {
            list.attr('comparator', 'createdAt');
            return list;
          }
        },
        batchSize: {
          value: config.chat.batchSize,
          type: 'number'
        },
        upperThreshold: {
          value: config.chat.upperThreshold,
          type: 'number'
        },
        lowerThreshold: {
          value: config.chat.lowerThreshold,
          type: 'number'
        },
        cleaning: {
          value: false,
          type: 'boolean'
        },
        isFocused: {
          value: false,
          type: 'boolean'
        }
      },
      Message: Message
    },
    events: {
      '{Message} newInstance': function( Message, ev, message ) {
        if (!message.isNew()) {
          this.scope.buffer.push(message);
        }
      },
      '{buffer} change': function( list, ev, how, type, val ) {
        if (!this.timer && /(add|remove)/.test(type) && list.length) {
          if (this.scope.isFocused) {
            this.timer = requestAnimationFrame(can.proxy(this.processBatch, this));
          } else {
            can.batch.afterPreviousEvents(can.proxy(this.processBatch, this));
          }
        }
      },
      processBatch: function() {
        delete this.timer;

        var scope = this.scope;

        var upperThreshold = scope.upperThreshold,
          lowerThreshold = scope.lowerThreshold,
          batchSize = scope.batchSize,
          messages = scope.messages,
          buffer = scope.buffer,
          count = 0;

        can.batch.start();

        for (var i = buffer.length - 1; count < batchSize && i >= 0; i--) {
          var message = buffer.pop();

          if (!~messages.indexOf(message)) {
            count++;
            messages.push(message);
          }
        }

        if (messages.length >= upperThreshold) {
          this.scope.attr('cleaning', true);
        }

        if (messages.length <= lowerThreshold) {
          this.scope.attr('cleaning', false);
        }

        if (this.scope.cleaning) {
          for (var i = 0; i < 5 && messages.length > lowerThreshold; i++) {
            messages.shift();
          }
        }

        can.batch.stop();
      }
    }
  });
});
There’s an example ;)
Christopher Oliphant
@RALifeCoach
Mar 24 2016 19:29
Thanks folks - I will apply what I can and get back to you
Justin Meyer
@justinbmeyer
Mar 24 2016 19:29
@RALifeCoach this might have been proposed already, but are you rendering more than you need to?
For instance, I've seen people do:
{{#each things}}
   <li>
        <div class="{{^visible}}hidden{{/visible}}"> LOT OF STUFF </div>
   </li>
{{/each}}
instead of
{{#each things}}
   <li>
        {{#visible}}
        <div> LOT OF STUFF </div>
        {{/visible}}
   </li>
{{/each}}
Christopher Oliphant
@RALifeCoach
Mar 24 2016 19:35
The main #each is actually outside of CanJs. It is in another module. It loops through the array of 100 and instantiates a new can.Construct for each row. It then calls .render for the created row. In the render I build the data object, instantiate the Map, create the stache fragment, which fires off the main component.
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 24 2016 19:35
@RALifeCoach sorry I wasnt here, the stuff do a great job
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 24 2016 20:35
@daffl thank you cc @smiper
Christopher Oliphant
@RALifeCoach
Mar 24 2016 20:35
I am getting an error in helper.if
Thomas Sieverding
@Bajix
Mar 24 2016 20:35
What error?
Christopher Oliphant
@RALifeCoach
Mar 24 2016 20:36
can.custom.js:4909 Uncaught TypeError: options.inverse is not a function
Thomas Sieverding
@Bajix
Mar 24 2016 20:36
Paste your template
Christopher Oliphant
@RALifeCoach
Mar 24 2016 20:37
options is a function, instead of an Object
my template is 226 lines long
Thomas Sieverding
@Bajix
Mar 24 2016 20:38
Well, it sounds you have a helper that takes a specific number of arguments, and is trying to read a compute instead of the options object
Christopher Oliphant
@RALifeCoach
Mar 24 2016 20:38
yes I would agree
Thomas Sieverding
@Bajix
Mar 24 2016 20:38
IMO your issue isn’t with the if helper
Christopher Oliphant
@RALifeCoach
Mar 24 2016 20:39
however, how do I find where?
Thomas Sieverding
@Bajix
Mar 24 2016 20:39
Examine the stack
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 24 2016 20:41
@RALifeCoach can you paste just the part of the template where you use the helper?
Christopher Oliphant
@RALifeCoach
Mar 24 2016 20:42
here is the stache from one of the sub-components
{{firstName}} {{lastName}}

{{#is isActive 'true'}}
    {{#if multiCourse}}
        &nbsp;({{courseCode}})
    {{/if}}

    {{^eq playerCurrentRound tournCurrentRound}}
        {{#if isLessThan(options.currentRound, 10)}}
            &nbsp;#
        {{/if}}
    {{/eq}}
{{/is}}

{{#is isAmateur 'true'}}
    &nbsp;(a)
{{/is}}
isLessThan is a helper
Thomas Sieverding
@Bajix
Mar 24 2016 20:43
options.currentRound?
Christopher Oliphant
@RALifeCoach
Mar 24 2016 20:45
not a helper
but also not correct
Thomas Sieverding
@Bajix
Mar 24 2016 20:46
Sure your error isn’t in isLessThan?
Christopher Oliphant
@RALifeCoach
Mar 24 2016 20:48
I am working on performance improvements. It was working - one row at a time. I changed things to process 10 rows - to do that I restructured some of my data and put a {{#players}} round everything
the one row was working - now it isn;t
I have no problem that created a problem - what I want to know is WHERE?
the diagnostics are not helpful.
Thomas Sieverding
@Bajix
Mar 24 2016 20:49
Yea that’s tough. You could probably examine the intermediate’s to determine that
Do you know much about debugging?
ie breakpoints, stacks etc
Christopher Oliphant
@RALifeCoach
Mar 24 2016 20:50
I thought I did, but apparently not
yes I understand breakpoints and stacks
Thomas Sieverding
@Bajix
Mar 24 2016 20:50
You can walk up/down the call stack and access the context
Christopher Oliphant
@RALifeCoach
Mar 24 2016 20:51
great, how?
at what level of the 30 odd calls in the stack will I find “This is the line of stache I was working on.”?
Thomas Sieverding
@Bajix
Mar 24 2016 20:55
You wouldn’t, but you could look for the element, or the intermediate
I think hydrate maybe would work
Ok I know
Look for batchRenderer / mustache_core.js:180
Christopher Oliphant
@RALifeCoach
Mar 24 2016 21:00
oh good, I am not making much progress
Thomas Sieverding
@Bajix
Mar 24 2016 21:00
You’ll see the function name in the stack trace
Look for batchRenderer
Christopher Oliphant
@RALifeCoach
Mar 24 2016 21:00
branchRenderer?
Thomas Sieverding
@Bajix
Mar 24 2016 21:00
yes
Christopher Oliphant
@RALifeCoach
Mar 24 2016 21:01
okay - what am I looking for?
Thomas Sieverding
@Bajix
Mar 24 2016 21:01
nodeList will have the expression in it
You can also examine parentSectionNodeList expression to get a little bit more context
Christopher Oliphant
@RALifeCoach
Mar 24 2016 21:04
sorry for the delay - working on more than one thing at this time
Bingo - you are a genius!
Thomas Sieverding
@Bajix
Mar 24 2016 21:05
I try ;p
What’s the expression?
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:09
{{#if function param}} instead of {{#if function(param)}}
Thomas Sieverding
@Bajix
Mar 24 2016 22:10
Ah, so I was right earlier when I said you were calling an expression with the wrong number of arguments
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:10
yes you were - it was finding where in the 225 line file that was the problem
but that didn’t solve my performance issues
Thomas Sieverding
@Bajix
Mar 24 2016 22:11
finding where? you can multi-file search if you know the expression
Now you know though! When in doubt, use the call stack to get the offending expression via branchRenderer
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:12
yes - but all I knew was ‘you have a problem’ once you showed me how to find the code that had the problem - then iot was easy to find
yes - thanks for that
Thomas Sieverding
@Bajix
Mar 24 2016 22:12
np
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:12
but I still have the performance issue
Thomas Sieverding
@Bajix
Mar 24 2016 22:13
If you know your way around the stack, it’s easy to figure out anything
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:13
I moved all 156 rows into a single component, instead of create 156 maps and components
but it didn’t change the over all time
Thomas Sieverding
@Bajix
Mar 24 2016 22:14
Just make a gist with your template
I can’t give you feedback blind
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:15
jsbin okay?
Thomas Sieverding
@Bajix
Mar 24 2016 22:15
k
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:23
Thomas Sieverding
@Bajix
Mar 24 2016 22:25
safeValue?
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:26
a function in my map
        safeValue: function(value, ctr) {
            if ((value === null) || (value === '') || (value === undefined)) {
                return '--';
            }

            if (value === 0) {
                return 'E';
            }

            return value;
        },
there are several functions getting called - none are more than 15 lines long
Thomas Sieverding
@Bajix
Mar 24 2016 22:28
Why don’t you pass the player itself into the player-name component?
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:29
can I pass an object?
Thomas Sieverding
@Bajix
Mar 24 2016 22:29
Yes
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:29
nice
Thomas Sieverding
@Bajix
Mar 24 2016 22:29
You could do <player-name {player}=“player”/>
You should also use the new binding syntax
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:30
new binding syntax?
Thomas Sieverding
@Bajix
Mar 24 2016 22:31
<country-flag {country}="player.player_bio.country"></country-flag>
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:31
what’s the difference?
Thomas Sieverding
@Bajix
Mar 24 2016 22:32
Your use of underscores is regretable. You should use camel case as it converts nicely with kebab case
{foo-bar}=“fooBar"
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:33
I am using what I am getting
this is old code
Thomas Sieverding
@Bajix
Mar 24 2016 22:33
Fair
<country-flag country="{{player.player_bio.country}}"></country-flag>
That will do multiple computes
It’s doing a read compute of {{player.player_bio.country}}
And a 2-way compute against the result of that w/ country
<country-flag {country}="player.player_bio.country"></country-flag>
This however will bind to changes in player.player_bio.country, and update the country property of country-flag
Much cheaper
Passing in person into person-name will help a lot too
Basically all of your bindings are incorrect
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:37
can I use {isActive}=“isActive” or {is-active}=“IsActive”
Thomas Sieverding
@Bajix
Mar 24 2016 22:37
{is-active}=“IsActive”
The property name will always be converted to lower case kebab, then from kebab to camel case
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:38
can I pass in the results of a function? {xxx}=“function param”
Thomas Sieverding
@Bajix
Mar 24 2016 22:39
Yes, that should be fine I believe, however it’s preferable to use parseModel to clean your data whenever possible
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:39
parseModel?
Thomas Sieverding
@Bajix
Mar 24 2016 22:40
can.Model.parseModel
You’d use that to clean your data
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:41
okay
Thomas Sieverding
@Bajix
Mar 24 2016 22:42
For example, I have a channel model that has users, and I use parseModel to convert my users prop into a users array
parseModel: function( data, xhr ) {
  if (typeof data === 'string') {
    return {
      _id: data
    };
  }

  var __v = data.__v,
    _id = data._id;

  if (_id && typeof __v === 'number' && Channel.store.hasOwnProperty(_id)) {
    var channel = Channel.store[_id];

    if (channel.__v > __v) {
      delete data.__v;
      delete data.userCount;
      delete data.guestCount;
    }
  }

  can.batch.start();

  [
    'moderators',
    'bannedUsers',
    'bootedUsers'
  ].forEach(function( key ) {
    if (data.hasOwnProperty(key)) {
      data[key] = User.models(data[key]);
    }
  });

  if (data.owner) {
    can.extend(data.owner, {
      isModerator: true,
      isOwner: true
    });

    data.owner = User.model(data.owner);
  }

  can.batch.stop();

  return data;
},
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:42
the data is being retrieved outside of CanJS
Thomas Sieverding
@Bajix
Mar 24 2016 22:43
Doesn’t matter, you’d still call model/models on the PJSO, which in turn calls parseModel/parseModels
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:43
however, I could execute some of the methods before loading the map
Thomas Sieverding
@Bajix
Mar 24 2016 22:43
I do the above to ensure I’m always utilize model stores
sure
Christopher Oliphant
@RALifeCoach
Mar 24 2016 22:44
you’re getting ahead of me just now - let me focus on the stache portion as that is by far the worst offender
Thomas Sieverding
@Bajix
Mar 24 2016 22:44
myAjax.then(filter).then(Channel.models)
something like that