Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Chris Gomez
@akagomez
In fact, our hope is that there is seldom a need to manipulate DOM outside of a template.
espretto
@espretto
viewModel suits it better i agree, if only events in components was renamed to control and Map#serialize to Map#toJSON and ..
Chris Gomez
@akagomez
But if you do need to manipulate DOM via JS, you should do it in an event handler bound to a “state” change (i.e. viewModel property change event)
espretto
@espretto
well in this case i'd like to bind a property to third party plugin which wraps an element and has its own events, setup and teardown functions (google.maps.StreetViewPanorama)
so i went about it like this:
Component.extend({
  viewModel: {
    internalProp: compute({
      get: function () {
        // missing element access here
      },
      set: '', // set
      on: '', // bind to the plugin's custom events
      off: '', // unbind from the plugin's custom events
    })
  },
  events: {
    inserted: '', // init 3rd party plugin on element
    removed: '' // teardown 3rd party plugin from element
  }
});
espretto
@espretto
i ended up constructing the computed properties within the inserted event handler where the plugin's instance is created as well. i set those onto the scope/viewModel but am not sure if i myself have to tear them down or whether the framework will do it for me?
Chris Gomez
@akagomez
You’ve got the right idea. I personally would just create the bindings to properties in inserted though.
You’ll have to remove those yourself I think.
espretto
@espretto
how do you do that? calling scope.prop.off() or can.unbindAndTeardown? from within events.off or events.removed? will i have to call this._super.apply(this, arguments) if i override one of those? will this._super work inside component.events?
does the removed event occur after the element has been removed or just before that?
Chris Gomez
@akagomez
inserted: function () {
  var scope = this.scope;
  this.plugin = new Plugin();
  this.plugin.on(‘event’, function (data) { scope.attr(‘relevantProperty’, data); }
},
removed: function () {
  this.plugin.off(‘event’);
}
This is, if I’m understanding you correctly.
espretto
@espretto
what about
scope: { ... },
events: {
  inserted: function () {
    // ..init
    this.scope.attr('computed', compute(initial, {
      // get, set, on, off // bind to some plugin value
     }));
  },
  removed: function () {
    // do i have to tear down the computed? even if its on the scope thus within range of canjs?
  }
}
Justin Meyer
@justinbmeyer
@espretto don't use computes on the prototype
use the define plugin
much better
espretto
@espretto

sth like

scope: function (tagAttrs, parentScope, elem) {
  return {
    define: {
      computed: {
        // `value/Value, type/Type, get, set, serialize` etc.
        // access to `elem` yes, but without the `on` and `off` options this is a dead end, what now?
      }
    }
  }
}

using the define plugin there is no on and off options, how to circumvent that?

Chris Gomez
@akagomez
@espretto I’ve never needed on/off in the context of a view model. What’s your use case?
espretto
@espretto
this one (see settings object to compute)
    var input = document.getElementById("age")
    var value = can.compute("",{
        get: function(){
            return input.value;
        },
        set: function(newVal){
            input.value = newVal;
        },
        on: function(updated){
            input.addEventListener("change", updated, false);
        },
        off: function(updated){
            input.removeEventListener("change", updated, false);
        }
    })
in my case the value that is set/get/listened to is hidden within the plugin which has it's own methods i.e. not canjs' event system to get/set the value and listen to changes
espretto
@espretto
sure i could add and remove the listeners as you suggested within inserted and removed with the listeners setting and changing scope/viewModel properties but that scatters the whole logic to maintain one attribute over three places sope/viewModel events.inserted and events.removed which is way inferior to the above almost self-contained approach. sry, i have to leave, i'll be back later this day
just leave me what you think - i'll @akagomez you once i have the jsbin ready for the other issue.
thank you for your time. the help is very much appreciated!
espretto
@espretto
@akagomez here goes my computed request scenario http://jsbin.com/noxajixonu/edit?js,console,output
Chris Gomez
@akagomez
@espretto The promise compute won’t be run unless something is bound to it. Either in the template, in the events object, or directly (compute.bind(‘change’)).
Also, you have '{scope.promise} change’: function () { … }. change events in CanJS are not the same as in other libraries.
A change means that some property on an entire object has changed.
For instance..
var map = new can.Map({ foo: ‘bar’, boo: ‘baz’ });
map.bind(‘change’, function () { console.log(‘!!!’) });
map.attr(‘foo’, ‘baz’); //-> !!!
map.attr(‘boo’, ‘bar’); //-> !!!
What you likely wanted was…
var map = new can.Map({ foo: ‘bar’, boo: ‘baz’ });
map.bind(‘boo’, function () { console.log(‘!!!’) });
map.attr(‘foo’, ‘baz’); //-> 
map.attr(‘boo’, ‘bar’); //-> !!!
Or, rather…
‘{scope} promise’: function () { … }
The reason I mention this is that change events have a lot of overhead. For performance reasons they should be avoided when possible.
espretto
@espretto
i tried that, but still the promise now keep re-evaluating itself, plus i'd prefer a solution without a noop binding
good to know that about change
Chris Gomez
@akagomez
The promise keeps re-evaluating because state goes from pending to resolved on every call to the promise compute.
Since promise is dependent on state, it causes a loop.
espretto
@espretto

it seems the promise's call to attr('state', state)sets up a dependency if i'm not mistaken, anyway.
if you could fix the jsbin to work without binding a noop handler to work correctly i.e.

  • update the state when promise changes and when resolved/rejected
  • update the promise if idKey changes
  • update the model when promise resolves

that would grant me a good night sleep!

Chris Gomez
@akagomez
@espretto Are you really on 2.0.3?
Chris Gomez
@akagomez
@espretto The binding on set seems to be a 2.0.3 bug. If you reference latest, your approach works fine: http://jsbin.com/xahaxugobi/1/edit?html,js,console,output
espretto
@espretto
2.0.3 was what i found in jsbin's list, my bad. the binding on set persists in latest though see here. your solution does work for me, however intercepting the idKey setter kind of defeats the purpose of observables, after all, idKey shouldn't have to know what depends on it at all. i'll call it a day. again thanks for your time and efforts! hope to see you around here soon.
Chris Gomez
@akagomez
@espretto Sorry, I must’ve linked you incorrectly. This is your original code running on latest. It works as I think you’d expect: http://jsbin.com/kimuzenele/3/edit?html,js,console,output
Now, as for this new example. Let me look into it.
Diana Whitten
@hurgleburgler
Should steal-tools be available to install through bower?
Diana Whitten
@hurgleburgler
disregard, gonna ask in the steal room :)
opolyo01
@opolyo01
is stache passes index while iterating over collection or I need to write a helper?
in handlebars I would do this -- tabindex='{{@index}}'
getting NaN with stache
dylanrtt
@dylanrtt
@opolyo01 that should work. perhaps you are iterating over an object instead of a list/array in which case you probably want @key
opolyo01
@opolyo01
nope {{#dimensionList}} .. {{/dimensionList}}
dimensionList --> Array