How to do day to day Javascript stuff with Angular js? [closed] - javascript

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
over the past 3-4 days I have looked in to Angular js. From the look of it (with tutorials & videos) it looks pretty intuitive to use.But when I actually began to replace my current web app code with Angular js I faced lot of issues to startup.
For example if on a certain event I want some HTML to be added to an already present element somewhere in the DOM then by traditional jQuery route i'll simply get the element and add HTML. I can not fathom how to do the exact same thing with Angular because DOM manipulation is just not advised in Angular controller.So how do I access the element that I am supposed to expand.
Another example could be when I have to reset a Form element at some point. Again I face the dilemma of using jQuery style element selector inside Angular controller.
Could somebody please explain it to me how to do all these things with Angular.

Let me answer your title question first off: don't.
AngularJS is a powerful tool (and I'm only scratching it's surface, having worked exclusively on angular for 2 months # work, now) but it is far too opinionated for it to be a good choice for scripting. It has a bit of a learning curve (not too steep, but certainly more so than the "hey, {{model}} is magic!" intro you find on their page. Don't take me wrong - I absolutely love it, it is extremely structured, which forces me to be organized, and makes the code extremely scalable. So, if you are willing to learn its "MO", you'll love it once you do.
Now, on DOM manipulation: you can go about it in numerous ways, but basically, if you want DOM manipulation, you want a directive. The tutorials are good to help you on this, but if you are moderately good at JS, I advise you to explore the source code (ngRepeat, which you may already know, is a straight up regular directive, exactly like one you could create). An angular scope is tied to a DOM element, and vice versa. In a directive, you can address the element it is tied to, and there use jQuery (or any other framework, or just plain JS) to change it. A change can be tied to the moment the element appears, to the changing of a model (via the $watch function), or to an event you specify (and trigger) yourself (see $broadcast ad $emit).
I changed an example script that tackled a different kind of problem (namely triggering events on the end of a ngRepeat) to include a bit of different ways of dealing with DOM: http://plnkr.co/edit/or5mys

In Angular, all the DOM manipulation code resides in directives. So if you need to add HTML to an already present element, for example loading the content of a modal dialog from a remote url, you will need to write a directive for that. See the documentation here: Directives in AngularJS

It depends on what type of DOM manipulation you want to do; as others have said, a Directive could work, but that's more for complex DOM stuff or repeatable widgets. For regular form stuf, if it's simply filling in text somewhere you can just do that with the contoller's scope.
For example if you want to update a status message, instead of directly updating the DOM, you can bind it to a field on your scope:
<div>{{statusMsg}}</div>
and in your controller, when appropriate:
scope.statusMsg = 'Done loading';
Since Angular has two-way data binding, the DOM will automatically get updated with the message.
For the example of a form reset, your form would be bound to a model, so to reset the form you would just reset the model. Here is a very simple example: http://jsfiddle.net/Kbsqx/

Related

Polymer - Load different components dynamically

I'm a Polymer novice, but I guess what the answer will be...
Recently I came across with this issue: I got to loop through a collection of elements (using dom-repeat) and display its contents. But every element has a unique display and bindings, making it almost impossible to display each element dynamically. The ideal scenario would be to load a different component for each display type, but it looks like there is no easy way to achieve this.
Some options I have been thinking of were the following:
Using dom-if but it would add crap to my resulting HTML.
Is there a dom-switch? If it were something like that and didn't leave empty template tags (as it would do with dom-if) it would be nice.
It's possible to load a component dynamically? Using something like this: <[[item.type]] item-configuration=[[item.configuration]]></[[item.type]]>
Any other ideas? I would really appreciate any ideas or solutions or at least a workaround for my issue.
TL;DR; you can't
Polymer (and Web Components in general I guess) are best when used in a declarative way. Out-of-the-box your best solution is dynamically creating elements and adding to DOM or messy use of dom-if.
(potential) OPTION 1
I guess you could fairly easily implement a dom-switch element to work like
<template-switch switch="[[some.value]]">
<template-case case="10">
<element-one></element-one>
</template-case>
<template-case case="20">
<element-two></element-two>
</template>
<template-default>
<element-one></element-one>
</template-default>
</dom-switch>
I wrote this off the top of my head. There are multiple ways to implement such an element. A crucial decision is whether to use <template> internally or not. In this plunk I've implemented such element without templates but simply using content distribution.
OPTION 2
There is also Polymer.Templatizer.
Faced with a similar issue of choosing element to render dynamically I created this Plunk as a proof of concept.
As you see, you extend the <template> element with custom rules, which match against a model. You then bind the matched template's nodes with the model using Polymer.Templatizer.
Thanks to Templatizer, you don't have to pollute your actual element with conditionals and still get full binding functionality.
I'm working on a more feature-complete solution. If you're interested I could move it to a separate repository and publish.

Refactor a huge form with a Javascript Framework

I have a huge form divided into sections. It has about eight sections and it will simply be unwieldy to put this giant form on one page. No one would ever slog through it.
I also decided that dividing it into pages will also not be ideal because if someone is section 6 and realizes he needs to change something on section 2.
I created a client side solution using Jquery. So You just click tabs representing sections of the form. So you hide a previous section section when you click on a new section and handle all the logic of saving server side making sure someone can switch back and forth while validating data on each section. Behind the scenes its still one huge form. A lot of Jquery is used to make it work properly. It is tightly coupled to the DOM and no one can understand the code unless I explain.
Also when making changes you have to make sure there are no lingering events which cause something unexpected to affect another section of the code.
Its quickly becoming a monster. I think this is an ideal problem a Javascript framework would solve but I have no idea where to start. How would it fit in the context of Javascript MVC especially all the DOM manipulation and event driven approach I use. any ideas or suggestions are welcome.
I would consider using AngularJS
This is a real war story - I was struggling with the exact same issue you are. Huge unwieldy form, needed it to be refactored into re-usable components(since one portion of the form included a pricing page).
Getting started is pretty easy, I'd suggest to look at the tutorial before you see my solution.
Here's how I solved my issue -
Have one controller for your form.
Use UI-router for making sub-routes of your form (e.g. /signup/profile, /signup/address etc); all of them being controlled by your main controller. Store them in separate HTML files as templates being rendered on a view (yay!)
Also, you don't need a major commitment to use angular, you can just use it for this purpose in your app.
Hope this helps.
Frameworks that handle data binding and embedded control statements sound like they would be ideal for an issue like this, like Knockout.js or Angular.js.
For example, with knockout, you could have a segment like:
<div data-bind="if: someCondition">
Only show this section of the form if the condition is met
....
</div>

AngularJS: directives vs. controllers - What logic to put where? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm quite new to angular and try to really learn how to organize my code, so future coworkers will be able to find their way around it quickly.
One rule I know is "If it manipulates the DOM, put it into a directive", which I abide by.
But still there are times where I am unsure where to put my methods, as I can put them into the main app controller, into a controller supplied as the "controller" option within the directive or even within the function that inits the directive (option "link").
With filters and services it's pretty clear to me, but with controllers and directives the line becomes pretty blurry.
I already realized that even with a little app I spread some of the code here and there and it's already confusing, even to myself. So I'd like to get some Tipps on organizing my code better.
So I guess my main question is:
1) Is there a good rule of thumb to know what code to put where?
Or if this is too abstract here are some examples:
2) I have a directive with a template which I only use within my app. Something should happen, when I click on the element. I already know its preferable to use the ng-click directive over binding a click event within the linked function.
But where should I define the method supplied in ng-click?
A) The main controller of the app.
B) The "link" function of the directive.
C) Add a controller to the directive (using the "controller" option) and define it there.
3) Would the answer to 2) be different if I plan to reuse the directive elsewhere?
4) Different Scenario:
I have a Button and when clicked and dragged it should move a completely unrelated Element.
Should I...
A) Create one directive and influence template & behavior based on a passed attribute?
B) Create two directives (one for the handle, one for the target Element)
If so, it again poses the question of where to put the methods to handle the dragging?
Notes:
I am aware the answers might be a little dependent on personal opinion, but I kinda hope there are some "rules" or "right ways to do it" to which I can abide by for future development.
I didn't include any code for conciseness reasons.
Should it be needed for an answer I'd be happy to provide it.
thank you for your time.
First of all, great question. I think every new-with-angular developer struggles with the differences with all the given components (controller, directive, service, filter etc.).
Let's start with the basic formal definition:
Directives are markers on a DOM element that tell AngularJS's HTML compiler to attach a specified behavior to that DOM element.
And on the other hand
Controller is a JavaScript constructor function that is used to augment the Angular Scope
The defined behavior does guide us through some rule-of-thumbs.
So for your questions above:
In simple words, we user controllers to manage an area (scope) in
The HTML template with all the great abilities a controller brings
(two-way-binding, scoped behavior, services injections etc.) And we
Use directives when we wish to manipulate an existing HTML element or
Custom out own, in most scenarios - when we think about reusing
This elements.
That depends on the context of what ng-click should do. Lets say you have your customized directive for a numeric input that has a customized designed and behavior as you defined in your directive configuration. And you use it in a form that ng-click suppose to pop a modal with optional values and use it in a different place in the application and ng-click will do something else. In this case the function need to be a scope.fucntion. but let's say both location and every other will do exactly the same, this take the function to the directive scope.
Answered above :)
Each of your options will do, this where "opinion" takes in and less rule-of-thumbs exists. why? because both ways will work when each has it pros and cons. The rule of thumb I can find in the scenario is that if both elements are part of the directive template, I would expect the 'behavious' (the dragging function) to be part of the directive scope.
Good luck
1) Is there a good rule of thumb to know what code to put where?
Lots of things at play here; and I'm not sure that there is a 'directives vs controllers' battle going on. They seem different enough to me. Directives can have their own controllers, if you didn't know.
I view directives as a single, specific, set of encapsulated code including the HTML (View) and JavaScript code (Controller). I use directives when I want to reuse something as an 'encapsulated' component.
If I just have a bit of JavaScript code that I want to reuse; I'll put in an AngularJS service which I see as just a collection of JavaScript code without any HTML.
I have a directive with a template which I only use within my app.
Something should happen, when I click on the element. I already know
its preferable to use the ng-click directive over binding a click
event within the linked function. But where should I define the method
supplied in ng-click?
I would define the handler as part of the directive's isolated scope; something like this:
scope:
{
onButtonClick: '&onButtonClick'
}
Define default behavior as part of the Directive's link or controller.
link: function ( $scope, element, attrs ) {
$scope.myDefaultButtonClick = function(){
// do stuff
}
this.onInit = function(){
if(!$scope.onButtonClick){
$scope.onButtonClick = $scope.myDefaultButtonClick;
}
}
this.onInit();
}
In your JavaScript; you can call the function that is passed in as an argument:
$scope.onButtonClick();
And you can do the same in your HTML template.
<img src="button.png" ng-click="onButtonClick()">
3) Would the answer to 2) be different if I plan to reuse the
directive elsewhere?
If I do not plan for reuse; I would probably not use a directive.
I have a Button and when clicked and dragged it should move a completely unrelated Element.
Should I...
A) Create one directive and influence template & behavior based on a passed attribute?
B) Create two directives (one for the handle, one for the target Element)
If so, it again poses the question of where to put the methods to handle the dragging?
I would chose item A probably; passing in the element that needs to be manipulated as an argument to the directive. However, it depends how much I care about re usability of this piece of functionality.
Everything I say should be considered subjective.

How does one figure out what piece of JavaScript changes a given HTML tag?

I often want to change some releatively minor detail about how JS changes the DOM, but I can never figure out which function in what script changes a given tag. How does one do this?
For example, on this page, I want whatever JS is adding the "selected" class to various a tags to also add it to the enclosing li tags. However, I have no idea how to figure out where this is taking place.
Clarification: As much as I'd like an answer to my current, specific conundrum, I'd much rather be taught how to figure it out myself.
CLARIFICATION:Is there a way to point at a certain object in the DOM and find out what script(s) are/were accessing/modifying that object? In other words "watch" that object for JS access/modification.
What you need is DOM breakpoints in WebKit's Developer Tools.
They're designed for tracking DOM mutation events - such as change of an attribute of an element (which is your case), element removal, or addition of subelement. You can refer to tutorial in DevTools documentation.
In basic cases you might want to use grep for searching the strings such as "selected" in your code.
I’m not aware of any debugging tools that’ll tell you when a DOM element is being acted upon by a script.
(If anyone knows of any, dear lord please tell me about them — I’m a freelancer, so I spend most of my working days trying to figure out old, knotty DOM-manipulating JavaScript that someone else wrote.)
You basically have to search through every bit of JavaScript file included in the page, and identify lines that might be taking the action you’re seeing.
In the case of a class name being added to an element, an obvious search is for the class name itself, although that’s not guaranteed to work. E.g.
el.className = el.className + 'sel' + 'elected'
If jQuery is in use, I’d definitely search for addClass.
Once you think you’ve found the right line, then if you have access to the JavaScript code, you can change it and see if your change takes effect.
(And, because view source is still a part of the web, you can get access to the code by saving it all to your computer.)

Any value in JavaScript/HTML Decoupling? if so how?

Lately I've been writing more and more JavaScript for the websites I've been creating. And I can't help but think that I'm doing something wrong, or there has to be a better way.
I have a clean separation of concerns on the server side, but on the client side, I find myself having entire sections of JavaScript that are dependent on specific element id's and class names, etc. For example, on one page, that has a lot of form fields, I may have a section of code that looks like:
$(document).ready(function() {
$("#ButtonID1").button();
$("#Grid").someGridFunction();
$(".data-fields").datepicker();
$(".submit-links").click(function() { this.closest("form").submit(); });
});
What I'd almost prefer is some way for the HTML elements to request to obtain certain functionality. Something like:
<input type="text" data-make="datepicker" />
But even that is flawed, because customization of that would require more and more attributes on the HTML element to detail specifics. I had a similar setup done with KnockoutJS and I really wasn't happy with the HTML that was required.
Maybe something along the lines of this:
<input type="text" data-init="buildDefaultDatePicker" />
where "buildDefaultDatePicker" is a JavaScript function that handles the necessary work.
In the end, the question I have is two fold. Is there any value in separating the JavaScript from the UI in regards to specific element ids and class names. And if so, what patterns, and or methods have you used to achieve this?
(Note, I'm using jQuery syntax above, but I think this question is framework agnostic, so shouldn't matter for the answers)
It looks to me like you've got the right idea already (using classes to apply JavaScript enhancement to specific elements). Using a custom attribute such as data-make or data-init would be just another (more fiddly) way of doing the same thing. The way you have things already, specific classes can be used as the request to obtain certain functionality.
The method I'd advise is keeping a clean separation between your HTML and JavaScript. The JavaScript should always be in external files, and written to target page elements on $(document).ready to provide the requested functionality.
I'd just use a class to signify the elements you want to attach behavior to. It has a semantic meaning, and you aren't coupling the html IDs or their locations into the javascript.
In the likely event that you need some specifics, like say a minimum or maximum date on a date picker, a light sprinkling of data attributes I think is an elegant way to provide it. But anything that would require more than a few data attributes is probably, in reality, a whole new kind of thing that deserves its own class, thus removing the need for the data attributes. For example, you might have a datepicker class, and find yourself constantly providing a minimum date of today to force a future date selection. Well, just make a 'futuredatepicker' class instead.

Categories

Resources