Get model for specific dom element

5,655 views
Skip to first unread message

Silas Hansen

unread,
Jan 13, 2013, 9:31:10 AM1/13/13
to ang...@googlegroups.com
I'm trying to get the specific model object for an HTML element while traversing and making changes to model representing my DOM.
The traversing takes place outside the controller and any directives.

My current approach right now is something ugly like: 

var scope = angular.element(ta[0]).scope();
scope.$apply(function () {
eval("scope." + ta.attr("ng-model") + " = ''")
});

ta is the jquery element im currently manipulating.


This works, but isn't there another way that doesn't involve eval?





Pawel Kozlowski

unread,
Jan 13, 2013, 9:36:26 AM1/13/13
to ang...@googlegroups.com
Hi!

Could you describe what you are trying to do, functionally speaking?

Your code looks very fishy....

Cheers,
Pawel
> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To post to this group, send email to ang...@googlegroups.com.
> To unsubscribe from this group, send email to
> angular+u...@googlegroups.com.
> Visit this group at http://groups.google.com/group/angular?hl=en-US.
>
>



--
Question? Send a fiddle
(http://jsfiddle.net/pkozlowski_opensource/Q2NpJ/) or a plunk
(http://plnkr.co/)
Need help with jsFiddle? Check this:
http://pkozlowskios.wordpress.com/2012/08/12/using-jsfiddle-with-angularjs/

Looking for UI widget library for AngularJS? Here you go:
http://angular-ui.github.com/

Silas Hansen

unread,
Jan 13, 2013, 9:52:51 AM1/13/13
to ang...@googlegroups.com
Of course

Lets say I have a number of input text field, all bound to some properties on the scope of the surrounding controller.
Next to each input text field, I have a button that clears the field.

I have some jquery eventhandler that listens to a click event on each deletebutton, finds the corresponding input field and attempts to clear it.

To clear it:
I need to clear the variable that the text field is bound to inside the scope. I don't know how to get a reference to the specifik variable that an HTML element is bound to through "ng-model", so my approach was to just concatenate the "ng-model" attribute name with the scope and evaluate the expression that resets (assigns empty string) the field , which seems to work perfectly. But yes, it seems fishy.


I hope that makes a little more sense.

Pawel Kozlowski

unread,
Jan 13, 2013, 10:00:14 AM1/13/13
to ang...@googlegroups.com
Hi!

OK, I see.

What you should be doing is to clear a model value to which the input
is bound. AngularJS will take of repainting inputs.

Something like:
<input ng-model="myModel"><button ng-click="myModel = ''">Clear</button>
Live code here: http://plnkr.co/edit/TE15BicKkCykVSrWru7L?p=preview

With AngularJS we should be mutating model and let it repaint UI based
on model changes. Direct DOM manipulation outside of a directive is
really not the AngularJS way of approaching things.

Hope that above makes sense, if not please send a modified plunk with
what you are trying to do.

Cheers,
Pawel


On Sun, Jan 13, 2013 at 3:52 PM, Silas Hansen <silas...@gmail.com> wrote:
> . I don't know how to get a reference to the specifik variable that an HTML
> element is bound to through "ng-model", so my approach was to just
> concatenate the "ng-model" attribute name with the scope and evaluate the
> expression that resets (assigns empty string) the field , which seems to
> work perfectly. But yes, it seems fishy




Silas Hansen

unread,
Jan 14, 2013, 2:53:11 PM1/14/13
to ang...@googlegroups.com
Hey

Thanks for the answer.
I'm looking for a more generic way of modifying the scope variables that the HTML elements are bound to without having to manually write a click handler for each of them.
I've used evil (eval) to reach my goal in the attached example, in the hope that someone knows how a generic behaviour would be accomplished with angular.


Maybe I'm still just missing something important in the angular paradigme... I hope so :)

Pawel Kozlowski

unread,
Jan 14, 2013, 3:07:54 PM1/14/13
to ang...@googlegroups.com
Hi!

Uhh, it is still far away from the AngularJS-way :-)

The good news is that it is so, so much easier with AngularJS (just
one possible way of doing it):
http://plnkr.co/edit/ycE9YAbVfoEzewH8p5Jn?p=preview

If you want to make AngularJS work for you instead of fighting with
it, try to follow those rules:
1) Never, ever manipulate DOM (attributes, nodes etc.) outside of a
directive. But I really mean it :-)
2) Focus on model. Change the model they way you want it to be and
allow AngularJS to do the heavy-lifting.
3) Let go of the jQuery way - AngularJS is radically different!

I would suggest not including jQuery during your early experiments
with AngularJS - you can go far, very far this way.

Cheers,
Pawel
> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To post to this group, send email to ang...@googlegroups.com.
> To unsubscribe from this group, send email to
> angular+u...@googlegroups.com.
> Visit this group at http://groups.google.com/group/angular?hl=en-US.
>
>



Silas Hansen

unread,
Jan 15, 2013, 1:40:46 PM1/15/13
to ang...@googlegroups.com
Hi Pawel

Thanks you for taking the time to help out.
I still dont find the solution as generic as how I usually express things in jQuery.

Declaretively I would like the following: "For any input wrapped in a clearable-text class element, configure an existing sibling button to clear the property that the input is bound to".

Is it just so that angular lacks the ability to do range-operations (based on some selector or criteria) like jQuery and I should just live with that? Or would it be possible using a directive? If it is, what would it look like?


I looked over most of the tutorials on the angular concepts, but didn't find much. Feel free to link me any litterature that explains what and why in more detail.

Pawel Kozlowski

unread,
Jan 15, 2013, 1:53:59 PM1/15/13
to ang...@googlegroups.com
Hi!

I will let other to comment but just few remarks:

1) AngularJS is different, very, very different from jQuery in its
approach to building UI. In short (very, very simplified):
a) jQuery = focus on finding DOM elements and manipulating them
b) AngularJS = focus on mutating model and don't think about DOM elements

So it takes a bit of time to adjust but the resulting code is much
smaller and cleaner IMHO.

On Tue, Jan 15, 2013 at 7:40 PM, Silas Hansen <silas...@gmail.com> wrote:

> Declaretively I would like the following: "For any input wrapped in a
> clearable-text class element, configure an existing sibling button to clear
> the property that the input is bound to".

For me it sounds imperative :-) Here you've got a step-by-step
instruction of how to do things.
With AngularJS you change model and don't instruct it about DOM manipulations.

> Is it just so that angular lacks the ability to do range-operations (based
> on some selector or criteria) like jQuery and I should just live with that?

I think that this is wrong question. As I've said, AngularJS is
radically different. So yes, I think you should give it a try and see
how it works for you.

> Or would it be possible using a directive? If it is, what would it look
> like?

IMO the solution I've send you is close to what I would do in a
real-life scenario if those inputs are not generated dynamically.

Anyway, I would suggest getting rid of jQuery while learning
AngularJS. jQuery is a fantastic library and serves many purposes but
if you want to learn AngularJS don't try to use as jQuery.

Cheers,
Pawel

Silas Hansen

unread,
Jan 15, 2013, 2:27:56 PM1/15/13
to ang...@googlegroups.com
Okay, thanks for taking the time Pawel, it is greatly appreciated -  I will get rid of jQuery and see how far I get.

Only thing I'm missing atm is the "for each match, do this" way of describing behavior - I will look further into directives.
By declarative, I was referring to what I wanted to be done, not how I wanted it done.

Comments from others are still very welcome :)

Peter Bacon Darwin

unread,
Jan 15, 2013, 2:55:30 PM1/15/13
to ang...@googlegroups.com
Hi Silas,
What exactly is wrong with Pawel's solution?  In you solution you have to provide a class on every input element that you want to be cleared and a button next to it.  Something like this:

<input class="clearText" ng-model="myModel"><button>Clear</button>

And then provide a jQuery handler that will clear the value of the input when this button is clicked.

This seems simple but this handler is fragile to the layout of your buttons and inputs.  If you (or say your designer) decided that in some cases the button should be within a div or that there should be some element in between the input and the handler or that the button should come before the input then suddenly your handler becomes complicated or you have to start having multiple classes and handlers for each.  Moreover what does clearText mean?  As a new person coming to this code, I would have to have trawled through all your JS to check what it means (if anything) to put clearText on my input as a CSS class.

Pawel's suggested solution is very transparent and flexible.

<input ng-model="myModel"><button ng-click="myModel=''">Clear</button>

The designer is free to move the button wherever they like in the DOM without having to worry about breaking the functionality.  It is clear to anyone who understands Angular binding what the button is doing, immediately on looking at the code.

You say your don't want to have to bind handlers to each input manually.  If this is about saving you some typing you are basically swapping

class="clearText" 

for

ng-click="myModel=''"

which doesn't seem like a big deal, especially when you take into account that this is "all" the code, whereas your solution would have all the code of the jQuery handler too. If you are worried about performance, because you have millions of these inputs and you don't want to have loads and loads of click handlers everywhere, then I would question why you have so many inputs in the first place but then add that it is possible to write a directive that can pick up delegated clicks.  But again this puts you in a similar situation with having to tell this handler what to clear.




--

Dave Merrill

unread,
Jan 15, 2013, 3:40:31 PM1/15/13
to ang...@googlegroups.com
I think in Silas's jQuery version, you don't need the button in the markup. The idea is that the code examines the DOM, detects the clearable fields, and adds this functionality to them, including the button. Angular doesn't typically do that kind of rule-based DOM manipulation.

Even if you wrote an attribute-based directive that would do that for its contents, if I'm not mistaken, Angular will re-render the contents at will, destroying the added buttons.

I'm a relative Angular newb, but I'm not sure there's an Angular analog to that kind of tool.

Dave

Peter Bacon Darwin

unread,
Jan 15, 2013, 3:53:11 PM1/15/13
to ang...@googlegroups.com
Ah, well.  Of course you could always do something like this: http://plnkr.co/edit/KqMIAC6MKPAVrA6LUY87?p=preview
But if you want to get generic with this then it is a lot harder.
Pete

Silas Hansen

unread,
Jan 16, 2013, 2:03:59 PM1/16/13
to ang...@googlegroups.com
Hey Peter

Thats a brilliant solution the last plunk, just the kind of functionality I was seeking!
Very much appreciated and educational!

And thanks for your previous answer also - It all adds to the understanding of how to go about doing stuff the AngularJS way :)
Reply all
Reply to author
Forward
0 new messages