Hey there, I have some elements with the same custom directive but different values in my page.
I want to get all elements with that directive to process on them.
When I use this code:
Vue.directive('can', function (value) {
console.log(value)
})
it just gave me the first element with the can directive, not all of them, so how I can get all of the elements with the can directive?!
Update:
my elements are like so:
<button v-can="'register-permission'">Register</button>
<button v-can="'buy-permission'">Buy</button>
<button v-can="'Sell-permission'">Sell</button>
I want to access all buttons with the v-can directive in page! How can it be done?
Following Vuejs documentation on custom directive, I would access all of them like this:
Vue.directive('can', {
bind: function (el, binding, vnode) {
console.log(binding.expression)
}
})
Related
I want to invoke a method on click of Any div with a given class. In JQuery it was a trivial one liner. Do we have something similar in Angular?
I know we can use a (click) binding to invoke a method on click. But that would require a separate binding for each instance of the div. I want a generic way to bind every div for the given class - as we used to do with JQuery selectors
In Angular you can create a custom directive, assign it to the required blocks and create a click listener via #HostListener.
For example:
HTML
<div appMyDirective>
div 1
</div>
<div appMyDirective>
div 2
</div>
Directive
#Directive({
selector: '[appMyDirective]'
})
export class MyDirectiveDirective {
constructor() { }
#HostListener('click') onClick() {
console.log('Привет')
}
}
May be it suit you
Angular has absolutely different approach. Instead of querying the DOM, we typically bind the event handlers in the markup.
<button (click)="onSave()">Save</button>
Event binding
Can you please elaborate on what you are trying to achieve,will specify the basic of using click and ngClass in angular see if it helps
In you HTML file
<div class="my_class" (click)="clickDiv()"
[ngClass]="isActive ? 'active' : 'notActive'">
Some content
</div>
In .ts file
isActive : boolean = false ;
clickDiv(){
this.isActive = !this.isActive;
}
I have custom attribute my-custom-attribute which contains the id for the element I need to add and remove this attribute depending on the boolean.
I already tried this code and it is working fine, is there any way to make it using vuejs directives?
HTML:
<div my-custom-attribute="my_element">
...
</div>
JS:
const el = document.getElementById("some_id");
if(my_bool) {
el.setAttribute("my-custom-attribute", "#my-element");
} else {
el.removeAttribute("my-custom-attribute")
}
You can register a directive as global using the below example, it provides you three lifecycle hooks for you to control the behavior, read the following and try to implement. Let us know if any problem occurs with your implementation and start a separate thread
https://v2.vuejs.org/v2/guide/custom-directive.html
Vue.directive('my-custom-directive', {
// When the bound element is inserted into the DOM...
inserted: function (el) {
// Focus the element
el.focus()
}
})
I have a custom directive called HandleScroll and I need to add this directive to all input elements. When I initially built it , it was only needed on one input elements so I added it manually as:
< Input handle-scroll....
But now I realize that I need to add this directive to each and every input element. Is there an easy way to do this using Javascript or will I have to sit and manually add this directive to each input tag ?
Update----Thank you everyone for your help, due to some updates I no longer need to use the directive , but need to bind an event listener to each input field. I've posted the new question at: Adding an event listener to each input field , if you can help please do , I greatly appreciate it !
In your directive class, you can set the selector in your decorator :
#Directive({
selector: 'input'
})
export class HandleScroll...
You can wrap input with angular component. And just use the component everywhere.
<app-input-with-directive></app-input-with-directive>
In AngularJS you can use following.
function MyCtrl($scope, $compile, $window, $document) {
$window.onload = function() {
var inputs = $document[0].querySelectorAll('input');
inputs.forEach(input => {
input.setAttribute('handle-scroll', true);
$compile(input, $scope);
});
};
}
Basically, we are trying to add a new attribute to each input element on the page and recompiling the element.
I currently need to be more specific in my functionality for a class toggle that needs to only occur in the children within the element being clicked. I have a class of ".node" and when this is clicked it should toggle a class on it's child ".node-dropdown". I have multiple of these nodes with (click)="showNodeDropdown" and currently all the node dropdowns are being hidden or shown at the same time.
HTML
<div class="node" *ngIf="authService.isInternalUser()" (click)="showNodeDropdown()">
<span class=" fa fa-clock-o node-icon"></span>
<p>Menu Title</p>
Keep in mind there are multiple of these elements using (click)="showNodeDropdown()" throughout my page and this is just one example.
JS
showNodeDropdown() {
$('.node-dropdown').toggleClass('hidden');
}
I tried changing my JS to be something like $(this).children('.node-dropdown).toggleClass('hidden');
however (this) is currently defined only as "object Object"
Is there a way I can get the element that was clicked and set it to (this) so that I can toggle only on it's children? Thanks in advance for any help.
Here are two Angular ways to get the clicked element:
Pass the event target to the handler:
<div (click)="showNodeDropdown($event.target)" ... >
Define a template reference variable, and pass it to the handler:
<div #myDiv (click)="showNodeDropdown(myDiv)" ... >
In both cases, the event handler can be written as:
showNodeDropdown(element: HTMLElement) {
let nodes = element.querySelectorAll(".node-dropdown");
for (let i = 0; i < nodes.length; i++) {
nodes[i].classList.toggle("hidden");
}
}
or, using jQuery:
showNodeDropdown(element: HTMLElement) {
$(element).children(".node-dropdown").toggleClass("hidden");
}
It is recommended not to use jQuery inside of Angular Applications. If you need to select DOM Elements use #ViewChild instead:
https://angular.io/api/core/ViewChild
Here an example:
Controller:
#ViewChildren(TestComponent) test: QueryList<TestComponent>
Template:
<ng-container *ngFor="let player_ of players; let i = index">
<test></test>
</ng-container>
to print the <test> Elements just do the following inside the TypeScript Controller:
console.log(this.test)
So, you can access them like any variabled declared in the Controller.
You can pass $event object here:
(click)="showNodeDropdown($event)"
and then use
showNodeDropdown(event) {
$(event.target).toggleClass('hidden');
}
My recomendation is not use jquery, instead create a Directive
import { Directive, HostListener, HostBinding } from '#angular/core';
#Directive({
selector: '[appNodeDropdown]'
})
export class NodeDropdownDirective {
#HostBinding('class.hidden') isOpen = false;
#HostListener('click') toggleOpen(evenData: Event){
this.isOpen = !this.isOpen;
}
}
and use it like this
<div appNodeDropdown *ngIf="authService.isInternalUser()">
of course remember to register the directive in the "Declarations" array of module of the component.
Although I know it is best not to use JQuery in my angular application thanks to #messerbill , I still needed to come up with an answer to handle this issue using JQuery. I was able to set an ID to each div that utilized this (click) and pass the ID through the click like so:
<div class="node" id="booking-node" (click)="showNodeDropdown('#booking-node')">
showNodeDropdown (id: string) {
$('.node-dropdown').addClass('hidden');
$(id).children('.node-dropdown').toggleClass('hidden');
}
This allowed me to gain the results that I was looking for. Keep in mind this is not the best answer, as not using JQuery at all would be the ideal solution, however I did not have this option so this is the JQuery work around.
I have to add a list of checkboxes dynamically. I then need to know which one performed the click, then ask if it's checked or not.
I have this code:
$('#MyContainerOfChecksDiv').click( '.MySelectorClass', function(){
if ("MyCheckClicked".is(':checked'))
{
//...here i need to use the label and id
}
else{...}
})
using "$(this)" i get the "MyDiv", obviously using $(this).find('input:checkbox') I get the whole list of checks.
I have to get this checkbox because I need to use its properties.
Add a formal parameter to click handler and use it like this
$('#myDiv').click('.MySelectorClass', function (e) {
if ($(e.target).is(':checked')) {
alert(e.target.id);
}
})
fiddle
Also it's not quite clear to me how you distinguish dynamically added elements and static. Do you have different class for them? If so then you dynamic and static elements can have different handlers and this will be the way to tell whether it was created dynamically
To delegate to dynamic elements you have to use .on(). The element that you clicked on will be in this.
$("#myDiv").on("click", ".MySelectorClass", function() {
if (this.clicked) {
// here you can use this.id
} else {
// ...
}
});
You can't use .click() to delegate like you tried. You're just binding the click handler to the DIV, and the string ".MySelectorClass" is being passed as additional data to the handler.