milo icon indicating copy to clipboard operation
milo copied to clipboard

Cannot create a simple class with item facet

Open jasoniangreen opened this issue 10 years ago • 17 comments

The following setup complains of Uncaught MixinError: method trigger already defined in host object

<ul ml-bind="[list]:todos">
    <li ml-bind="Todo:todo"></li>
</ul>
var Todo = milo.Component.createComponentClass('Todo', ['item']);
milo.registry.components.add(Todo);
milo(function(){
    milo.binder();
});

jasoniangreen avatar Aug 21 '14 19:08 jasoniangreen

I see some clumsy solutions... Don't like them. The workarounds are either to explicitly list all required facets in class definition (also clumsy) or to put item facet in template: ml-bind="Todo[item]:todo". But you know it probably...

epoberezkin avatar Aug 27 '14 09:08 epoberezkin

Yeah, I have been looking at it this morning.Should there not just be a different method for Facet$check to use which simply adds the facets to the component config... but I guess at this stage the config has already been run. Maybe something to iterate the facet config before the facets are instantiated, to look for requires. Hmm, not so simple.

jasoniangreen avatar Aug 27 '14 09:08 jasoniangreen

It looks like it could one day be a source of trouble, look at all the places we use it. You can search the project for require: ['

jasoniangreen avatar Aug 27 '14 10:08 jasoniangreen

There are 2 solutions

  1. We may pass an extra parameter to addFacet to prevent starting it in the case it is called from check. addFacet already has 4 parameters and in check it is called like addFacet(reqFacet) So it will become addFacet(addFacet, undefined, undefined, undefined, false); A bit ugly.
  2. Another idea is to track facets that were started (e.g. assign this._started = true in Component$start, which is empty now) to prevent them started for the second time. so instead of using allFacets('start') in Component$init we can iterate them and only start those that are not started already. Probably a bit less ugly... But some of the facets may have forgotten to call inherited start (as it was empty anyway), in which case they may be started twice if they are required... Unlikely we will be affected by it though. So we need to pick one :) Any better ideas?

epoberezkin avatar Aug 27 '14 10:08 epoberezkin

Or we can create another method addFacetWithoutStarting and call it from check... Maybe this one is the prettiest of all :)

epoberezkin avatar Aug 27 '14 10:08 epoberezkin

Maybe the last, given that it would more or less be an internal method, not used elsewhere. I had thought of the others too. I don't mind 2 either.

jasoniangreen avatar Aug 27 '14 10:08 jasoniangreen

actually, it is not working in some cases, as it makes, e.g., Data facet to be started before Container facet which it cannot do, as Container facet should be started before Data facet... Require enforces the order, but class declaration does not... We can rely on object order of course and simply re-order facets, but it is not good... And actually we are relying on it anyway :)

epoberezkin avatar Aug 27 '14 10:08 epoberezkin

I never liked this "require" idea :)

epoberezkin avatar Aug 27 '14 10:08 epoberezkin

Maybe it should just fire warnings for the requires.

jasoniangreen avatar Aug 27 '14 10:08 jasoniangreen

Even the facent._started idea is not so simple to implement because it needs to be checked in allFacets. I got it working by adding something horrible like this: !facet['_'+method+'ed']

jasoniangreen avatar Aug 27 '14 10:08 jasoniangreen

the fix is in the branch https://github.com/MailOnline/milo/tree/start-order, but more changes are needed before it can be merged. See #44

epoberezkin avatar Aug 27 '14 11:08 epoberezkin

The change to allFacets method should be based on some parameter, as it is simply designed to run a certain method on all facets, regardless whether it was run before. getState uses it too for example. I think we should simply iterate without allFacets if we want to check anything.

epoberezkin avatar Aug 27 '14 11:08 epoberezkin

Yeah, agreed.

jasoniangreen avatar Aug 27 '14 11:08 jasoniangreen

The fix I did works, it just exposes a potentially bigger issue of us relying on object iteration order when we start facets. We need to define some start order (#44)

epoberezkin avatar Aug 27 '14 11:08 epoberezkin

The example in examples/todomvc_class/index.html now loads without throwing, but the list simply doesn't work. I'll take a look.

jasoniangreen avatar Aug 27 '14 11:08 jasoniangreen

when you use the branch?

epoberezkin avatar Aug 27 '14 11:08 epoberezkin

As a temporary workaround, I suggest removing item from class definition and putting it in template... That's what we did in other places :)

epoberezkin avatar Aug 27 '14 11:08 epoberezkin