Here's an example. There's some general style issues in there because I
banged it together over ice cream.

http://plnkr.co/edit/XXOvE3?p=preview

Generally speaking:

I created a Potato factory which makes Potatoes. In a real model, creating
it may fire off some $http events or whatever else. But Potatoes are a
model. There's a silly little cache thing in there, so if you make a Potato
with id1, you can get the same potato back from the constructor function
later (again, something similar could be done with the constructor as well,
to prevent unnecessary $http calls if you already have the thing). The
potato's longUpdate function simulates some long-delay method that returns
a promise.

So the objects created by new Potato are models in the MVC sense - you can
pass them around as attributes to directives, and they can handle all the
model-level stuff. Load, verify, fire off events, stuff.

The potatoTag directive, shows the current state of the potato and lets you
edit it. When you hit the accept button, it fires off the longUpdate and
does a .then to show off status tracking. The .catch route won't ever
happen (since we never reject the promise), but it's good form I suppose.
Often you won't have to actually create a promise from scratch - most async
things return promises in angular.

There's also an initialized promise in the constructor, which would
simulate the model taking a while to actually finish initializing in
construction. You can wait on full initialization in the constructor and do
stuff in the then route if needs be. Also, if you use ui-router, you can
attach those to the resolve attribute of your state which would pause the
state transition until the promise resolves.

I put an ng-if on myOtherPotato in the actual main layout so it won't show
up until the model resolves, just to show off an in-page (rather than
route-level) way to handle that.

Anyway, I hope this helps.

e



On Wed, Jul 30, 2014 at 6:05 PM, Alexander Ventura <
[email protected]> wrote:

> Eric, those are some great ideas. I have heard about 1 before but have
> never been able to truly grok the method of doing that because of a lack of
> examples. Could you perhaps demonstrate with a really quick demo?
>
>
> On Wednesday, July 30, 2014 4:42:33 PM UTC-7, Eric Eslinger wrote:
>
>> A couple ideas off the top of my head (so they may be terrible):
>>
>> 1) this feels like a situation where a service object is a good idea.
>> Make a factory or something that creates your service object and inject it
>> in all the relevant places, instantiate it in the controller and pass it to
>> the directive. Then use the model to track state in both places.
>>
>> 2) Your service object (or other methods) could return promises. So
>> instantiate the directiveAPI and call method() on it, but know that method
>> returns a promise that only resolves after it's fully instantiated and
>> *then* it can do stuff.
>>
>> 3) Invert control by passing a method into the directive. Use the '&'
>> scope notation to shove a method onto your directive's scope, and then have
>> that method get called (like a callback, yo) when the funky startup on the
>> directive is done. At that point, the rest of the controller stuff can work.
>>
>> 4) You could combine 3 and 2 to pass in a promise object or something
>> like that, which could then be resolved to something in the directive and
>> you'd have a handle on the thenable from the controller context.
>>
>> 5) Really, I think (1) is the right answer here. If there's actual things
>> that have to be manipulated that the directive responds to in terms of DOM,
>> then you need a real Model object. Have the model return promises as
>> needed, and you can deal with proper async handling without needing to use
>> _.defer
>>
>> This is what I do, I've got factories that are model constructors, models
>> which can inflate themselves from the server using $http or from user
>> input, and directives which manipulate the DOM based on the model values.
>> But the controller on the parent scope doesn't have much to do with any of
>> that, it just wires models together into directives.
>>
>> hope this helps and isn't just a "late in the day, not enough caffeine"
>> braindump
>>
>> e
>>
>>
>> On Wed, Jul 30, 2014 at 4:10 PM, Alexander Ventura <[email protected]
>> > wrote:
>>
>>> Howdy y'all,
>>>
>>> Recently I implemented a way to communicate from a controller to a
>>> directive using an API object (since I hate dealing with events). Allow me
>>> to quickly demonstrate:
>>>
>>> module.controller('MyCtrl', function ($scope) {
>>>   $scope.directiveAPI = {};
>>>   function doStuffWithDirective () { $scope.directiveAPI.directiveMethod
>>> (); }
>>> });
>>>
>>>
>>> Now in the template:
>>>
>>> <my-directive api="directiveAPI"></my-directive>
>>>
>>> In the directive:
>>>
>>> module.directive('myDirective', function() {
>>>   return {
>>>     scope: { api: '=' },
>>>     link: function (scope) {
>>>       scope.api.directiveMethod = function() { ... };
>>>     }
>>>   };
>>> });
>>>
>>> At first, I was all smug and feeling smart about this implementation of
>>> controller-to-directive communication, but the more I thought about it, the
>>> more doubts I had about it being a good design. The first design kink
>>> happened when the controller needs to do something with the directive right
>>> as the controller is instantiated:
>>>
>>> module.controller('MyCtrl', function ($scope) {
>>>   $scope.directiveAPI = {};
>>>   _.defer($scope.directiveAPI.directiveMethod());
>>> });
>>>
>>> Notice, that I need to _.defer the execution of my code since the
>>> binding has not happened at that time.
>>>
>>> Now my questions for y'all is:
>>>
>>> Is this a good design choice for c-to-d communication?
>>> How can I avoid having to _.defer code execution?
>>>
>>> In my use case, the controller is driving the interaction with the user,
>>> while the directive handles some very complicated DOM manipulation
>>> ($compiles, transcludes, etc).
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "AngularJS" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> To post to this group, send email to [email protected].
>>>
>>> Visit this group at http://groups.google.com/group/angular.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>  --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/angular.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.

Reply via email to