In html i have a div
<div class="row" id='textdrag{{$index}}'>
I need to use the id to display context menu based on id,like.
$("#textdrag2").contextmenu(function (event) {
setcontextposition("text");
});
But for some reason the context menu is not displayed.
Its works just fine when i just use id="textdrag" without the $index
Why don't you append to the class instead and that way you wont have a flaky selector on a dynamic id. It is generally not a good idea to use a selector that will change.
<div class="row text-drag-cls" id='textdrag{{$index}}'>
$(".text-drag-cls").contextmenu(function (event) {
setcontextposition("text");
});
Hope that helps
Change your html to the following
<div class="row" id="{{ 'textdrag' + $index }}"></div>
Why it isn't working by current approach?
Basically your javascript is getting fire as soon as it loads, but that instance textdrag{{$index}} haven't evaluated $index value. Since the event haven't got attached to that DOM.
I'd rather recommend you to create directive for this functionality, which generally viable solution to play with DOM in AngularJS. By this approach you don't need to specify unique identifier to each element.
<div class="row" context-menu>
...
</div>
Directive
app.directive('contextMenu', [function(){
return {
link: function(scope, element, attrs) {
element.contextmenu(function (event) {
setcontextposition("text");
});
}
}
}])
Related
I can't seem to find the answer to my question or the correct angular way to do this. I understand it's partially subjective. I have an element that's clickable. Inside that element I also have another element that is clickable:
<li (click)="route($event, d, d.isdliked)" *ngFor="let d of dList; let i = index">
<div class="image-container" [ngStyle]="{ 'background-image': 'url(' + d.ImagePath + ')'}">
<div class="keep-container">
<div *ngIf="d.dliked" (click)="cantKeep()" class="liked">
<p>{{d.dLikes}}</p>
</div>
<div *ngIf="!d.dliked" (click)="keep(d, i)" class="not-liked">
<p>{{d.dLikes}}</p>
</div>
</div>
</div>
</li>
So the first click event in the li element will route the user to another page. The other to click event's do not route anywhere. But if I click on those two inner click events I get routed to my other page when I don't want to.
So I tried this little bit of code to check to see if the element that is clicked contains the class "keep-container":
route(element: Element, d: D, dIsLiked: boolean): void {
if (!element.classList.contains("keep-container")) {
this.router.navigate(['/dinfo']);
}
}
but this isn't working.
I tried with element.target of course and that didn't work. What am I doing wrong? I'll keep searching.
Main objective: If I click on the p tag
<p>{{d.dLikes}}</p> I want to check to see if it's inside the class "keep-container"
just use $event.stopPropagation() as usually you do in javascript
<div *ngIf="d.dliked" (click)="$event.stopPropagation();cantKeep()">...</div>
Well, I like in the same .html, you can pass the $event to the function cantKeep and make the stopPropagation in the .ts
<div *ngIf="d.dliked" (click)="cantKeep($event)">...</div>
cantKeep(event)
{
event.stopPropagation();
...rest of actions..
}
I am new to angularjs, just like many other developer, I was jquery developer. Now I have a question about directive.
example: if i have a directive like this:
app.directive('mydiv',function(){
return{
restrict:'AE',
template:'<div><ul><li></li><li></li><li></li></ul></div>', //of course in real case it will be use ng-repeat
link:function(scope,element,attr){
}
}
})
the confuse I have is,if I need to access any element,in jquery we can use $(this), how can we do it with angular way? Can I do like this:
link: function (scope, element, attrs) { //when hover show the delete icon for each msg and apply highlight class to it.
element.find('li').hover(
function(){
$(this).addClass('highlight');
scope.deleteicon=true;
},
function(){
$(this).removeClass('highlight');
scope.deleteicon=false;
});
}
You can access the element as the 1st argument (element argument in your case) of the link function itself. If you are using jquery with angular and loading jquery before angular the element` will be wrapped in jquery wrapper, i.e it will be a jquery object. If not angular uses a lighter subset of jquery called jqlite. It only provided a minimal functionality.
See element for details.
Instead of binding hover event manually you should use angular event binding and use ng-class instead of add/remove class. That way you perform things angular way and you do not need to manually invoke digest cycle via scope.$apply() for DOM updates with respect to scope updates (Which you need to do in the hover pseudo event in your example to reflect DOM updates based on scope property deleteicon).
An example implementation of your directive will look like this. There are numerous ways you can do this using angular built-in directives itself.
.directive('mydiv',function(){
return {
restrict:'AE',
scope:{items:"="}, //<-- data bound from parent scope via attribute
template:'<div><ul><li ng-mouseenter="toggleClass(true)" ng-mouseleave="toggleClass(false)" ng-class="{'highlight': action.deleteicon}" ng-repeat="item in items">{{item.name}}</li></ul></div>', //of course in real case it will be use ng-repeat
link:function(scope,element,attr){
scope.action = {deleteicon :true};
scope.toggleClass = function(show){
scope.action.deleteicon = show;
}
}
}
});
scope:{items:"="}, sets up 2 way binding if you wish to bind the data from the parent scope via attribute.
Instead of repeating li use a data model, say an array of items and use ng-repeat instead of duplicating the tag (unless you need to do it for sure). ex:- ng-repeat="item in items"
Use angular event bindings instead of binding the events manually, hover is nothing but nouseenter/mouseleave. So you can use respective angular directives and bind a function on the scope. i.e ng-mouseenter="toggleClass(true)" ng-mouseleave="toggleClass(false)".
Use ng-class bound to a scope variable to toggle the class. Let angular manage DOM manipulation for toggling the css class on the element. You just worry about the data being bound. i.e ng-class="{'highlight': action.deleteicon}"
You can find official documentation on angular built in directives/components.
Well, you used hover, but, you can use the MouseOver Directive.
As the following example:
<li ng-mouseover="high = true" ng-class="{'highlight':high}">Content</li>
Look at this plkr
Markup:
<div class="row" ng-app="myapp" ng-controller="myctrl">
<div class="col-lg-3 col-lg-push-3">
<ul class="list-group">
<li class="list-group-item" ng-init="myclass='hide'" ng-repeat="item in items"
ng-mouseenter="myclass = 'show'" ng-mouseleave="myclass='hide'">
<span>{{item}}</span>
<span ng-class="'pull-right glyphicon glyphicon-edit '+myclass"></span>
</li>
</ul>
</div>
</div>
Script:
angular.module('myapp', [])
.controller('myctrl', function ($scope) {
$scope.items = ['abc', 'xyz', 'klm'];
});
I want to do a simple thing:
I have an app, which has certain divs that in need to show (Only the specific one) and hide if clicked somewhere outside of it (All with the specific class for example).
This is easy using jquery:
$('some-class').style('display','none') //psuedo code here
How should i do the same with angular js?
A specific reason to do so:
I want to build a simple select drop-down (I don't want to use one that exist, i want to understand this...), when i click one, it suppose to open a div right beneath the button, when i click outside of it, it suppose to close not only this one, but some other elements like it in the app.
one point worth mentioning: Not all my select boxes are pre-rendered, some are dynamically added (inside directive), so not all of the are in the $scope, but inside them directives which has isolated scope.
Its better to make directives for these kind of things:
Make a directive for toggleDisplay as following
app.directive('toggleDisplay', function() {
return function(scope, element) {
element.bind('click', function() {
element.toggleClass('unneeded-class'); // or something else
});
};
});
and then you can apply this directive to any element in the html:
<div toggle-display></div>
You can make a drop down logic or kindof accordion etc following this pattern
How do i listen to a click anywhere in the app, that when i click it
and "that" element is not the select box, close all the select boxes?
let suppose you have that opend/dispalyed div that you want to hide when you click outside of it . give it a class "divvy" and attach the following directive to its wrapping container:
app.directive('toggleFocus', function() {
return function(scope, element) {
element.bind('click', function() {
if(!element.hasClass('divvy'))
angular.element(document.querySelector('.divvy')).css({display:'none'})
});
};
});
html:
<div toggle-focus>
<div class="divvy"></div>
</div>
It's in the angular documentation: https://docs.angularjs.org/api/ng/directive/ngShow
<!-- when $scope.myValue is truthy (element is visible) -->
<div ng-show="myValue"></div>
<!-- when $scope.myValue is falsy (element is hidden) -->
<div ng-show="myValue" class="ng-hide"></div>
just attach ng-show="whateverValue" to each div you want to hide/show based on whether "whateverValue" is true/false
I was wondering, say I have the following DOM structure in my View / Webpage
<div>
<p>I am some text or a comment or something</p>
X
</div>
<div>
<p>I am some text but this Div may have more content like IMG or inputs</p>
X
</div>
I'd like to add a method on the controller called deleteThisDiv that will remove the parent DIV of the href and all the DIV's contents (including the href I just clicked). This is easy with jQuery as I could just get the parent and use $target.remove() however I want to get out of the jQuery way of things and remove the item using AngularJS best practice. I know I could use jqLite as $target.remove() is supported and I guess I could climb the DOM tree to find the DIV but is there a better* way to do this (like using ng-show/ng-hide, etc)? Please note that I can add IDs to my HTML but I don't want to populate the HTML structure with IDs just yet.
When I say better I mean an AngularJS way! I just want to get out of the mind set of using jQuery for these things... please note that the HTML is coded and not produced by an array or looping through objects, etc
I believe the "angular way" would be to have the divs show conditionally using the ng-show directive if what you're looking for is a function that can show/hide the div. If you're looking to literally either have one or the other div in the DOM I'd take a look at ng-if or ng-switch.
Note that ng-if and ng-switch only evaluates once meaning you wouldn't be able to have a function that "removed" a DIV. ng-show on the other hand is evaluated on each $digest cycle
<div ng-show="someExpression>
<p>I am some text or a comment or something</p>
X
<!--Clicking this will show/hide the div-->
</div>
<div ng-if="someExpression">
<p>I am some text but this Div may have more content like IMG or inputs</p>
X
<!--Clicking this has no effect because ng-if is only evaluated once-->
</div>
Use ng-show...
<div ng-show="showFlag">
<p>I am some text or a comment or something</p>
X
</div>
in your controller you'll need to define the variable like:
$scope.showFlag= true;
You might be looking for this one.
module.controller('TestController',
function TestController($scope) {
$scope.deleteThisDiv = function ($event) {
$event.target.parentNode.parentNode.removeChild($event.target.parentNode);
};
});
I use this directive for very similar reasons:
<div destroyOnEvent="destroyThisDiv">
<p>I am some text or a comment or something</p>
X
</div>
.directive('destroyOnEvent',function($rootScope) {
return {
restrict : 'A',
link : function($scope,$element,$attrs) {
$rootScope.$on($attrs.destroyOnEvent,function() {
$element.remove();
});
}
}
});
I wrote a jquery plugin that allows users to use either touch or mouse (kind of like this) to resort a ul. The plugin works fine for updating the DOM but I'm not sure how to tell Angular to "update" the model binding. Specifically, the ng-click i have in the li doesn't fire after an li is moved. I'd also like to update the $index and tell the server what the new order is. Any ideas?
HTML:
<ul class="unstyled" ng-sortable>
<li ng-repeat="item in list.Items">
{{item.QuantityType.Name}} {{item.Name}} {{index}}
<button class="close" ng-click="deleteItem($index)" aria-hidden="true">×</button></li></ul>
Directive:
.directive('ngSortable', function () {
return {
link: function (scope, element) {
angular.element(element).draggableTouch({ onSortEndCallback: function () { scope.finishedSorting(); } });
}
};
})
EDIT: added code for more context.
Assuming that ng-click="deleteItem($index)" is not working
I would suggest you to pass item instead of $index so change your code as
ng-click="deleteItem(item)"
You can use indexOf function to find elements index in the array
scope.list.Items.indexOf(item)
Call the controller in your plugin after a click or touch. You can access the scope from outside your controller angular.element(domElement).scope() to get the current scope for the element.
Then update a $scope.sort (to send to server) and $index with the data in the plugin.