ac.composite.done() doesn't allow for data

ac.composite.done() does not allow for data to be passed to the view except that of its children. This makes for very boring controllers, as shown in all the examples, since none of the controllers for parent mojits does actually do anything except call ac.composite.done().  Parent mojits look like HTML <frameset>s since the only thing you can actually do is play around with the placeholders for the children in the html template.

However, that is not totally true, you can use ac.flush() to pass data from the parent to the view.  However, this is not free because it forces a second pass through the template handler and whatever logic is in between and it takes some time, specially if the controller is running in the server.  You have to design your template to tell apart the data coming from the call to ac.flush from that of the children via ac.composite.done.

It would be much cleaner if ac.composite.done could have taken a data argument as ac.done does and merge it with the data coming from the children and then send it all at once and get it processed all at once.

Even better it would be if ac.done() could figure out if it is a parent mojit or not and do either ac.done or ac.composite.done based on the configuration, which is readily available to it.  This would make it easier on the programmer and backward compatible since you might leave a deprecated ac.composite.done() as it is now simply adding a new ability to plain ac.done().   This would also add more versatility to mojits since it would allow the same mojit to have children (for example with more details) or not, depending on the configuration in application.json and the route leading to it, all with the same code.

However, I might be completely wrong.

5 Replies
  • No.

    You can always pass data to the "view" of the composite... just that it must be in the key "template"

    ac.composite.done( { template: { k1: "v1", k2: 123 } });

    and in the composite's view:

    <div ...>
       {{k1}} {{k2}} etc
  • Since I wrote this I have explored ac.composite.execute more in depth and found several goodies which come handy regarding this and my other post about communicating with children.

    Anyway, back to this, it would seem that the guy who wrote ac.composite.done had not talked with whomever did ac.done or, if the same person, suffered from amnesia in between the two. It would be easier if the two method were more alike.  If it is 
    ac.done(data, opts);
    it would make sense that it should be 
    ac.composite.done(data, opts);
    and not
    ac.composite.done({template: data});
    However, this is what I would like to suggest:
    ac.done = (function (original) {  return function (data, opts) {    var instance = ac.command.instance,      config = instance.config,      action = instance.action,      params = ac.params,      me = this;    if (config.hasOwnProperty('child')) {      config.children = {child:config.child};      delete config.child;    }    if (!config.children) {      return original.apply(this, arguments);    }    Y.each(config.children, function (opt) {      opt.action = opts.action || action || opt.action;      opt.params = Y.merge(opt.params, params, opts.params);    });    Y.mix(config.children, opts.children);    ac.composite.execute(config, function (childData, meta) {      original.call(me, Y.merge(data, childData), meta);    });  };})(ac.done);
    I am inserting the code above right after each action method that receives an action context in order to redefine it on the spot.  I don't really know where things are in Mojito (at least so far) so I can't patch it where I should so I improvised the patch above.

    So, what this does is to redefine ac.done so that it does what ac.composite.done does and, to some extent, what ac.composite.execute does.

    Basically, if it finds no child or children configuration in application.json it calls ac.done() as before.  If there is a child declaration there, it changes it to a children declaration and gives it a 'child' slot name.

    Then, for each of the children, as read from application.json, it allows for several overrides.

    A params option allows you to merge extra parameters into all children config.  This may be overridden by specific params settings on any of the children.  

    Also, the action option is taken from one explicitly set for that child, from a generic action option or from the action option of the parent mojit.

    Finally, a general merge allows for piling up all other settings which may override those in application.json.

    When that is done, it calls ac.composite.execute with that new configuration.  On return, it merges the data from the parent with that returned from the children and its metadata and calls the original ac.done.

    In this way, ac.done() combined with the settings coming from application.json and any possible overrides works in the same way both for regular mojits and composite ones.   It allows for several ways to provide overrides, generic ones and specific ones and spares going through ac.composite.execute.

    (continues ....)

  • Continued:

    For example, in my other post I wondered how to add a param to the params object which the parent had to retrieve and the child required.  This is the resulting code:

    model.read(idParent, function(err, rows) {  if (err) {    ac.error(err);    return;  }  ac.done({    debug:Y.JSON.stringify(rows),     data:rows  }, {params:{route: {idChild:rows[0].idChild}}});});
    A <div style="display:none">{{debug}}</div> placeholder lets me inspect the raw data if needed without messing the layout.

    As you can see here, I call ac.done() as I would normally do, though in fact, it is a composite mojit.  The composition of it is given in application.json as any other composite mojit and the data returned from the children is transparently merged with that of the parent.   In the options argument I am able to add a further parameter to the params.route argument.

    This is not fully tested and I really don't know how many other configuration options I should be handling.  I worked only with those I am aware of, which are really few, and those I was able to locate.   I'm just starting to work on this, but I would really love to see it in a future release of Mojito.  Do compare the size of the last code box with what it would take if I had to work with ac.composite.execute!  (which I did, and hated it!)

  • I seem to be unable to paste code from elsewhere so I posted them on github.  My patch and the usage example
  • This was solved a while ago when ac.done() and ac.composite.done() become equivalents in term of api.


Recent Posts

in Yahoo! Mojito