Scope watch problem

44 views
Skip to first unread message

Michał Kocztorz

unread,
Oct 16, 2014, 11:56:03 AM10/16/14
to ang...@googlegroups.com
Hi everyone!

I'm trying to get grasp od angular lately. It is awesome but I run into some trouble from time to time :).

I'll start with a link to fiddle: http://jsfiddle.net/2r71xsgm/4/

Best way to learn is to write code. So I figured out that I will create a directive(s) that will help me place and size divs using absolute positioning. 
Standard thing: relative positioned parent and absolute positioned children. 

But I wanted to do it angular way so the dimensions and placement of the div will be stored in a model (POJO):
{
    width: 2,
    height: 20,
    top: 10,
    left: 40,
    units: {
        width: {
            unit: 'em',
            unit2px: 14
        }
    }
};

Additional feature will be different units usage (not only pixels). Pixels will be the default ones though. However all the calculations will be done in pixels (mouse events return values in pixels). For the purpose of this question you can completely ignore units (it is not yet ready or used). So there is an object containing width, height, left and top all in pixels (the Model). It is created in controllers scope (hardcoded for testing). 

My idea was:
1. Create a directive that will place and size it (called it fmSpaceState). The placement of the element is the sole purpose of the directive.
2. Create a directive that will allow dragging that around (fmDraggable). It uses only the model to change the placement of the element. fmSpaceState should do the rest.
3. Create a directive that will allow resizing (not done yet, but will work on same pronciples as fmDraggable).

Problems:
- different units
I solved this by adding a service (fmModelSpaceStateMap) that takes the model and checks if units element is present. It has methods to operate on the model (getters and setters, each of them takes the model as first param - this service is stateless).

- isolated scope problem
I need it to be in isolated scope but only one directive can request that on element. Moreover the isolated scope has to be shared by all the directives. 

I decided to 
* use isolated scope on fmSpaceState as the main directive and bind the model from parent controller
* use controller and bind the scope to it in each of the directives
* require fmSpaceState in fmDraggable (sharing the controller)
This should give me shared isolated scope, however weird that sounds. Actually the controller is shared, but it is bound with the scope - so eventually the model from isolated scope is available in both directives through controller.

He're is a (kind of) diagram of how I think it looks like :)


In the end there should be only one instance of the model available for both directives.

All seems to work fine, but the watchers set on scope in fmSpaceState detect model change only once: on startup. Then the changes are not applied.
The model changes - I tested that with the two input fields that change when dragging the box. Try it out on fiddle by dragging the box. You'll see the model changes on drag (input fields are bound with it) but box stays put.

Thanks in advance!
Michał 




Sean Amoroso

unread,
Oct 17, 2014, 8:39:06 AM10/17/14
to ang...@googlegroups.com
The joys of isolated scopes.  I putzed around with your fiddle and looks like your scope.$watch's were off.  We've had better success using syntax like this:

        scope.$watch(function() { return scope.fmSSCtrl.spaceModel.left; }, function() {
                    element.css('left', scope.fmSSCtrl.getCssLeft());
                });

I've forked your fiddle with updated syntax.  

Sean Amoroso

unread,
Oct 17, 2014, 8:41:35 AM10/17/14
to ang...@googlegroups.com
 Looks like the main problem was not including the controllerAs syntax.  
 
This also works too:  scope.$watch('fmSSCtrl.spaceModel.top', function() {
                    element.css('top', scope.fmSSCtrl.getCssTop());
                });

Michał Kocztorz

unread,
Oct 20, 2014, 8:37:04 AM10/20/14
to ang...@googlegroups.com
First of all thank you for solving it :).

I could swear I tried that and it failed. I must have messed something in the process or leave some other debug code that broke it for me so eventually I gave up.

Now when this works, I have more general question: Is this correct approach to solving this kind of problem in angular world? Could I do it in cleaner/better way?


--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/X0oaFp_vh8c/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.



--
Best regards,

Michał Kocztorz

Skype ID: michal_kocztorz


Polcode SA

ul. Hoża 13, 00-528 Warszawa

http://www.polcode.com/

T: +48 22 825 50 47


Spółka zarejestrowana w Sądzie Rejonowym dla m.st. Warszawy XII, Wydział Gospodarczy KRS pod numerem 0000482235, NIP PL 701-021-72-88, o kapitale zakładowym 300.000 zł, wpłaconym w całości.

Reply all
Reply to author
Forward
0 new messages