DOM Manipulation like JQuery using AngularJS? - javascript

I have seen tutorials and other articles saying to not even include jQuery into a project when using Angular.js in order to make the transition as thorough as possible. However, how do we do simple DOM manipulations to css and other things like $('.item').css('top', '50px'); using only Angular? (or is this not possible)?

This is possible using the ng-class directive. On your element, you would say:
<div ng-class="{'classWithTop50':myScopeVariable}"></div>
Where classWithTop50 is defined in css as:
.classWithTop50{
top:50px;
}
When $scope.myScopeVariable is true, the element will have the class .classWithTop50

You can add classes like in ansewer reported by fairweather or you can also use ng-style to dynamically style the elements.
If you want more DOM manipulation then you can create a Directive for that element and do all the stuff using jqlite in the directive.

Angular comes with a lite version of jQuery, which allows a subset of jQuery. You can still include jQuery if you like (should be included before Angular).

Angular comes with a lite version of jQuery, which allows a subset of jQuery.
You can use this :
angular.element('.item').css('top', '50px');
AngularJS API Docs : element

Use ng-class directive:
(from angular doc)
<p ng-class="{'strike': deleted, 'bold': important, 'red': error}">Map Syntax Example</p>
=> this add the class 'strike' when the scope variable $scope.deleted == true, add the 'bold' class when $scope.important == true ...
Angular doc : http://docs.angularjs.org/api/ng.directive:ngClass
Don't think in jQuery, think in Angular (M-V-*).
angular.element() is there for directives DOM manipulations. DOM updates should be done with angular directives; css updates and animations with css classes.
see: "Thinking in AngularJS" if I have a jQuery background?

Related

Can i use queryselector in angular 9 application

QuerySelector is part of typescript or javascript. Can I use this in my angular application Which one needs to use instead of QuerySelector in angular application. Why I am asking, Suppose generating dynamic HTML on that condition I want to handle some event on the dynamically generated HTML.
On that condition, querySelector is very easy. But some people are telling like do not to use quesrySelector that is not good practice. So, How to handle these issue?
document.querySelector(".myclass");
document.querySelector("ul").querySelectorAll('li');
In order to dynamically render content you can use structural directive like *ngIf
<div>
<p *ngIf="displayElement; else showThis">Content</p>
<ng-template #showThis>
else content
</ng-template>
</div>
querySelector it's not a good practice in Angular.
Instead of using querySelector or similar from there, a declarative way can be used instead to access elements in the view directly:
<input #myname> // html
#ViewChild('myname') input; // add this in ClassComponent
ngAfterViewInit() {
console.log(this.input.nativeElement.value); // Input will be available in this lifecycle
}

Angular.js: ngSwitch to show/hide rather than add/remove DOM elements

As I've recently found out, ngSwitch acts a bit like ngIf, in that it outright removes elements from the DOM rather than just hide them. Now in my application this strikes me as both needlessly expensive and potentially problematic down the line (if I need to access properties of my hidden DOM elements). At the same time I like the cleanliness of the ngSwitch syntax as opposed to a bunch of different ngShow directives (which would not allow me to include a 'default' behaviour either). Is there any way I can modify the way this directive works to have it merely hide elements, not remove them altogether? Thanks.
OK, I understood better your need and I have the same need before.
I advice you to use ngSwitch with custom directives like this :
<div ng-switch="mode">
<directive-a ng-switch-when="a"></directive-a>
<directive-b ng-switch-when="b">...</directive-b>
<directive-c ng-switch-default>...</directive-c>
</div>
and in the definitions of your directives directiveA, directiveB and directiveC you use the templateUrl wich will use the cache from the second call of the directive.
The second approach is to use ng-show on every directive but I prefer the ng-switch because it let the dom lighter.
I know this is a bit old but I faced the same issue today and I managed to cache segments views by not using ngSwitch but directly the [hidden] attributes with the segment condition this way :
<ion-segment [(ngModel)]="segmentName">
<ion-segment-button value="profile">
Profile
</ion-segment-button>
<ion-segment-button value="friends">
Friends
</ion-segment-button>
</ion-segment>
<page-profile [hidden]="segmentName != 'profile'" ></page-profile>
<page-friends [hidden]="segmentName != 'friends'" ></page-friends>
Just replace ngSwitchCase by the [hidden] conditional
No, there isn't any way to keep nodes hidden as ngShow and ngHide do if you use ngSwitch. Only the ngSwitchWhen node will be created if its condition is true, all others are commented.
The advantage of ngSwitch is that the dom will be lighter.

Angular 4 DOM Manipulation and Search

Angular has these for DOM manipulation but I'm contemplating using jQuery for these functions: closest()/children().
So,
Is there an angular function that is identical to jQuery's function closest() which basically just returns the element?
Are there any alternatives for these functions in Angular without resorting writing native JS/TS operations to achieve those things just like jQuery, which does the dirty work? Or is alright to proceed with jQuery (I'm not dealing with template manipulation anyway)? Thanks.
Update
The window.getComputerStyle could easily replicate jquery's css().
Regarding jquery's selector: closest()
<div id="ample" #zero>
<div id="xample" #first>
<div #x>
</div>
<div #y>
</div>
</div>
</div>
I would like to know what could be an alternative operation for Angular. I could only think of making a function that traverses upward which jquery already does -give or take the DIVs and the element id are dynamically added/changed/deleted.
For example, from #y I want to know its nearest parent with an ID of ample. We know that the target element has a selector of #zero but retrieving it from div #y will take DOM traversal (which jquery simplifies using closest()) or some mapping/array operations that sorts out relations of the element which may be arduous in some point.
Is there is, one should avoid using jquery in Angular, here is an example how:
#Component({
selector: 'sample',
template: `
<span #tref>I am span</span>
`
})
export class SampleComponent implements AfterViewInit {
#ViewChild("tref") tref: ElementRef;
ngAfterViewInit(): void {
// outputs `I am span`
console.log(this.tref.nativeElement);
}
}
The keywords for you to search would be Elementref and Viewchild
JQuery is very powerful compared to what Angular is exposing for DOM manipulation. Sometimes it's very useful and very hard to ignore in an Angular application.
You can install it in your project but the only problem is that jQuery can access the DOM globally without encapsulation, so if you want to use good practices you should only access/modify DOM of the component you are using jQuery in, if you want to access/modify DOM outside of a component, you should pass needed data as #Input or use events to notify other components as #Output.
Do not forget to declare the variable $ in your component if you have installed it globally because typescript does not know what $ is.
declare var $ :any;
Using Jquery is not the angular way, but there are certain times where our hands are tied, only in those situations use jQuery. Use #viewchild or #viewchildren to get the DOM element.
span My name is XXX #name >
In .ts file
#ViewChildren('name') components: QueryList;
console.log(this.components.toArray());
You will be able to get the DOM. If you want only DOm element use #viewchild. In case of #viewchildren it will return an array of all the DOM elements which use the same selector or template reference variable.

Custom Attribute Directive being matched to ng-attr-myCustomAttribute

I am using a third party lib with the following custom attribute directive:
angular.directive('snapDrawer', function () {
'use strict';
return {
restrict: 'AE',
...
So if the attribute "snap-drawer" is found in an HTML element the directive implementation has a match and fires, for example:
<div snap-drawer></div>
I am using Angular 1.3 which has an "AllOrNothing" approach to ng-attr where if the value conditional is undefined then the attribute does not render like so:
<div ng-attr-snap-drawer="{{data.addSnapDrawer}}"></div>
100% fact this works, the value of data.addSnapDrawer in my controller is undefined and the snap-drawer attr does not render in the DOM
I have verified that Angular 1.3 does this AllOrNothing approach with ng-attr here: What is the best way to conditionally apply attributes in Angular? (take a look at Mathew Foscarini's answer)
BUT what does render in the DOM is:
<div ng-attr-snap-drawer="{{data.addSnapDrawer}}" class="snap-drawer snap-drawer-left" style=""></div>
So, unbelievably, the angular.directive('snapDrawer') is matching to "ng-attr-snap-drawer". How can this be, I am really shocked that AngularJS, in all its glory, has a bug like this.
I cannot find anything online. I cannot set snap-drawer="false" I need it to not appear in the DOM, which I achieved by upgrading from Angular 1.2 to 1.3.
This is old, but I stumbled upon something very similar. https://github.com/angular/angular.js/issues/16441 - angular authors made it this way.
You need to devise a different way (depending on your usecase) to conditionally apply directives (e.g. use ng-switch and have two versions of the HTML; one with the directive and one without, or have a terminal directive with high priority that evaluates the expression during the linking phase, applies the necessary directive(s) and compiles the element).

apply css style to multiple nodes having the same css class using dojo

I have been applying or changing the style for a CSS class in the javascript script, having a dojo f/w, like this,
this.sidePanel = query(".sidePanel", document.body())[0];
domStyle.set(this.sidePanel, {
height: "25%",
top: "334px"
});
This has worked fine but now I am having multiple nodes with similar CSS class. I wish to apply the new CSS style to the class and thereby all the nodes having the same class.
Is there some function in dojo which allows change in style to the CSS class directly without having to query for the node? Something like,
dojo.css.applyNewStyle('className', {'cssProperty': 'newValue'});
The dojo/query function returns a nodelist which you can operate on. If you also require the module dojo/NodeList-dom which extends dojo/query, you can do something like:
require(['dojo/query','dojo/NodeList-dom','dojo/domReady!'],function(query){
query('.red').style('background-color','black');
});
I made a quick jsfiddle to demonstrate this. The dojo reference guide has a list of additional methods you can call on a nodelist, including adding a css class, which might be what you want (if your new css values are static rather than dynamic).
And if you don't want to include the dojo/NodeList-dom module, you can still do this :
query(".sidePanel").forEach(function(node){ domStyle.set(node, { height: "25%", top: "334px" })});
...but yeah, dojo/NodeList-dom is more concise :-)
Yes there seems to be a way, but you don't need to use dojo. Check out this other post:
Changing CSS Values with Javascript

Categories

Resources