Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Matthew Phillips
@matthewp
thanks
espretto
@espretto
hi there, i'm new to gitted and canjs, anybody home?
Chris Gomez
@akagomez
Welcome.
espretto
@espretto
great! could you help me with some canjs basics?
Chris Gomez
@akagomez
I’ll do my best.
espretto
@espretto
i've been working with emberjs and knockoutjs but am still struggling atm with canjs observables/computed attributes - hands on: how do you typically wire up model requests depending on some observable e.g. the route?
as suggested in the docs i created a computed representing the request deferred
can.Map.extend({
   model: null,
    state: 'pending', 

    promise: compute(function () {
      var scope = this,
          promise;

      promise = ConfigModel
        .findOne({
          version: scope.attr('version'),
          title: scope.attr('panoTitle')
        })
        .then(function (model) {
          scope.attr('model', model);
        })
        .always(function () {
          scope.attr('state', promise.state());
        })
        .promise();

      scope.attr('state', promise.state());

      return promise;
    })
});
problem is the promise doesn't evaluate its dependencies until someone binds to it
Chris Gomez
@akagomez
@espretto That’s by design.
espretto
@espretto
makes sense, now..

if i rewrite state to depend on promise

...
state: compute(function () {
  return this.attr('promise').state();
});
...

the binding won't get set up. i intend to request {{state}} in my stache template to trigger the request - if that's how it's supposed to be.

return this.promise().state() won't setup the dependency either.
neither does stache's live-binding
espretto
@espretto
the only solution to force computed properties to evaluate their dependencies was to add
Component.extend({
  ...
  scope: MapCtr,
  events: {
    '{scope} promise': noop,
    ...
  }
  ...
});
Chris Gomez
@akagomez
So this.attr(‘promise’) didn’t call the promise’ compute function?
espretto
@espretto

yes it did, however, state does not revaluate itself when promise does. i was expecting any call to .attr would bind the computed being created to that attribute, but it doesn't. which is why i tried sth. like

Component.extend({
  ...
  scope: {
    promise: '...',
    state: compute(function (newState) {
      if (arguments.length) return newState;
      var self = this;
      self.bind('promise', function (evt, newPromise) {
        newPromise.always(function () {
          self.attr('state', this.state());
        })
      })
    })
  }
  ...
});

but that doesn't work either.

i think i basically try to achieve sth. like amd can/list/promise does
Chris Gomez
@akagomez
Is the promise property changing? Or is the state of the promise property changing?
espretto
@espretto
the state depends on promise
and promise depends on panoTitle and version
Chris Gomez
@akagomez
And you’re saying that promise does not get re-evaluated when panoTitle or version change?
espretto
@espretto
only after the call to bind (not stache live-binding but can.Map#bind)
attr doesn't duffice
the call to bind i implemented through the component's events object which btw i don't understand the naming of - why not just control?
Chris Gomez
@akagomez
Are you changing panoTitle and version with .attr(‘panoTitle’)?
espretto
@espretto
yes i am - well, actually
<input can-value="panoTitle"/>
Chris Gomez
@akagomez
Seems like you’re doing it all right. I’m curious if you can reproduce in a JSBin so I can take a closer look.
espretto
@espretto
yes i'd like to! this is so exciting: i only recently came to want to contribute to such "bigger" projects, and canjs so far is doing a great job. the fiddle will take me a few minutes - how to notify you? how did you @ me? ah i see - easy
do you have time for another question? this one should be easier
Chris Gomez
@akagomez
Yeah, sure. If I can’t answer I’m sure somebody else will.
espretto
@espretto
i figured defining components is the way to go for nested views so i'm building my whole app of them. how do give viewModel/scope (are these the same?) computed properties access to dom elements? here is the draft:
Component.extend({
  scope: {
    question: computed(function () {
      return howToAccessThisComponentsElement; // ?
    })
  }
})
Chris Gomez
@akagomez
Yes, viewModel and scope are the same. scope was recently renamed to viewModel for various reasons.
We strongly discourage DOM manipulation from the scope.
espretto
@espretto
as of 2.3-pre? i'm working with 2.2
Chris Gomez
@akagomez
2.2 uses scope as an alias to viewModel.
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