How to create dynamic expression in ng-class - angularjs

I have a ngRepeat element that has a delete button that triggers a confirmation message. I'm trying to make the confirmation message show with a dynamic expression like so:
<div ng-repeat="item in items">
<a ng-click="delete(item_id)"></a>
<span ng-class="{'show':'delete_'+item._id}">Are you sure you want to delete your review? </span>
</div>
Unfortunately I can't get the expression 'delete_'+item._id to show up in the ngClass directive. Can someone please offer a solution?

Using ng-class="{'show': 'delete_' + item._id}" will add the class show whenever the expression 'delete_' + item._id' evaluates to true (which is always). You probably want to have an expression next to show which is true when the user has clicked the a tag, i.e. ng-class="{'show': userWantsToDelete(item)}".
Additionally, if you want to add the class 'delete_' + item._id to the element, you can use angular expressions with class attribute, i.e., class="{{'delete_' + item._id}}" on the element.

try this one.
<a ng-click="delete = !delete">delete</a>
<span ng-class="{show: delete}">Are you sure you want to delete your review? </span>
if you want to show one delete confirmation message of last clicked <a>
In view
<a ng-click="delete(item._id)">delete</a>
<span ng-class="{show: item._id==delete_id}">Are you sure you want to delete your review? </span>
In controller
$scope.delete = function(id) {
$scope.delete_id = ($scope.delete_id == id) ? !id : id;
}

Related

Angularjs 1.5 replace directive element html

I want to built an ng-repeat with dynamic buttons that change according to $state.params so I wrapped them in a directive.
link:function(scope,element,attrs) {
$rootScope.$watch('params.source',function() {
var link = scope.link;
var name = scope.name;
var href = $state.href('home',{source:link});
if($state.params.source.indexOf(scope.link) == -1) {
var template = '<a href="'+href+'" class="btn
btn-default">'+name+'</a>';
}
else template = '<a href="'+href+'" class="btn
btn-default">'+name+' what!?</a>';
el = $compile(template)(scope);
element.replaceWith(el);
});
}
But after the the first change of params, element is forgotten and answers with Cannot read property 'replaceChild' of null
How can I replace element?
Edit: I need to swap the whole Element for sowmething else in final product, that's why I can't use ng-show or ng-if
Thanks!
You may be better off using ng-hide or ng-show in your html. Maybe something like this:
<div ng-repeat="yourArray as item">
<a href="{{item.href}}" class="btn
btn-default">{{item.name}} <section ng-show="conditionToShow">what!?</section></a>';
</div>
This is a bit cleaner of a solution and it keeps you from having to add a watch. Watches are expensive and you should avoid them if at all possible.
Edit:
<div ng-repeat="yourArray as item">
<div class="singleBtn" ng-show="conditionToShow" >
{{item.name}}
</div>
<div class="multiBtn" ng-hide="conditionToShow">
<a //rest of multi btn code
</div>
</div>
Because of the fact that Angular provides both ng-show and ng-hide directives this allows you to control the presentation of these elements based on just one conditional.(i.e. your state.params)
When it is true, it will show just one btn and when it's false it will show multiple buttons. If the logic needs to be reversed, just switch ng-show and ng-hide.
Hopefully I understood your need better this time.

Removing items from an array with Angular

Yes, it has been asked before, and I've read all the answers but nothing seems to work. So I'm asking for an extra pair of eyes to see if you can find any singularity in my code that is making it not work as it should. (I tried this code and logic somewhere else and it seems to work fine). No errors in the console by the way
I am simply trying to remove an item from the view when someone clicks the x on the picture.
Here is the controller
app.controller('galleryController', ['$scope', '$http', function($scope, $http) {
$http.get('data/galleries.json').success(function(data){
$scope.galleries = data;
}).error(function(error) {
console.log(error);
});
$scope.removeGalleryItem=function(gallery){
var removedGallery = $scope.galleries.indexOf(gallery);
$scope.galleries.splice(removedGallery, 1);
};
}]);
and my view
<div class="col-xs-12 col-md-3" ng-repeat="gallery in galleries" >
<a class="gallery-item" ng-href="{{gallery.img}}" ng-class="{true:'active',false:''}[checked]"
title="Nature Image 1" >
<div class="image">
<img ng-src="{{gallery.img}}" alt="Nature Image 1"/>
</div>
<div class="meta">
<strong>{{gallery.title}}</strong>
<span>{{gallery.desc}}</span>
</div>
</a>
<ul class="gallery-item-controls">
<li><label class="check"><input type="checkbox" class="icheckbox" ng-model="checked" /></label></li>
<li><span class="gallery-item-remove"><i class="fa fa-times" ng-click="removeGalleryItem(gallery)"></i></span></li>
</ul>
</div>
Angular 1.5.8
Thanks
You can pass an $index in your click function like this.
<i class="fa fa-times" ng-click="removeGalleryItem(galleryItem, $event , $index)">
and use $scope.galleries.splice(index, 1); inside your click function removeGalleryItem, make sure you have index parameter too like this.
$scope.removeGalleryItem = function(gallery , event, index){
$scope.galleries.splice(index, 1);
};
Hope this helps..
After doing some research I think the problem is that galleryController is defined somewhere in your markup but the elements in the gallery are not inside of where that controller is defined.
Referring to http://joli.sitedev.online/#/gallery. In file slidesController.js where galleryController is defined I put a break here and the code pauses:
I also put a break point here but the code does not pause when clicking on a delete button:
Looking at the markup I can't see any sign of ng-controller="galleryController" so I can't see how galleries in the ng-repeat is populated:
Maybe it is through this:
If it is through that then it would explain things as that directive has its own controller. Any further information would help and I'm sure we can clear this up.
If I understood correctly your question, if you want to delete a particular element both from DOM and Array containing these particular elements you can do the following:
<!-- Intercept that particular Element with $event-->
<i class="fa fa-times" ng-click="removeGalleryItem(galleryItem, $event)">
Lets supposing you are repeating some galleryItems and they have a name property.
And on your controller:
$scope.removeGalleryItem(galleryItem, $event){
//Save galleryItem Name
var itemName = $($event.currentTarget).name(); // if it has it on html
var itemName = galleryItem.name; // if it has a property
//Get the target and remove it
$($event.currentTarget).remove();
//Using lodash, loop through your array and remove that exact object from it.
//Ofc you can do a normal loop through it.
$scope.galleries = _.remove($scope.galleries, function(n) {
return n != itemName;
});
//Then, if the change does not happen in your DOM
$scope.$apply();
}
Hope I've been helpful.
I have made some changes to fix this issue and you can check it at this link.
The problem here was that there was a typo in the html snippet that was calling the removeGalleryItem(galleryItem, $event). The parameter name should have been gallery, not galleryItem, since there is no such object by the name galleryItem, hence inside this method, the parameter value was undefined. Once I fixed it, I was able to get the gallery object within the removeGalleryItem method and the following code worked absolutely fine:
$scope.removeGalleryItem=function(gallery){
var selectedGallery = $scope.galleries.indexOf(gallery);
$scope.galleries.splice(selectedGallery, 1);
};
Also note that, I have removed the $event attribute from the method declaration and from the html method call as we didn't need it in the above mentioned approach.
<i class="fa fa-times" ng-click="removeGalleryItem(gallery)"></i>

Why ng-show and ng-hide don't work with $route in angular?

In my application, I want to display a content based on active link, Example: if the link is "new" then "abc" and if link is "view" then "xyz" should be displayed. For that, I've used following code for my application.
<li>New</li>
<li>View</li>
<span class="white-text" ng-show="{{ $route.current.activetab === 'new' }}">new</span>
<span class="white-text" ng-show="{{ $route.current.activetab === 'view' }}">view</span>
When you use {{}}, the values are interpolated, i.e. the markup is replaced with the result of the expression. ngShow expects only the expression, so just use the function as it is, and it will work:
<span class="white-text" ng-show="$route.current.activetab === 'new' ">new</span>
<span class="white-text" ng-show="$route.current.activetab === 'view' ">view</span>
In general, you'll only want {{ }} when your expression / content should be displayed.
Hope this works!

angularjs how to trigger changes on object in scope

I have the $scope object (array of objects) like this
$scope.parts = [];
(content of $scope.parts is changing during 'run-time', not just filled once per page load)
Later, it some custom directive i show those parts in such manner:
<li ng-repeat="part in parts">
<span>{{part.name}}
<i class="fa fa-check"
tooltip="some tooltip"
...
</i>
</span>
</li>
According to some logic, i want to change 'fa-' class and tooltip text.
I can do it like this
<i class="fa"
ng-class="haveDescr(part.name)"
//and in directive's controller
$scope.haveDescr = function (partName) {
return someCondition ? 'fa-check' : 'fa-question-circle';
};
and so on for the tooltip, and... for every attribute i want to change?
Is there a better way, than to write a scope "check-function" for every attribute? How can i trigger changes in every single part/property of $scope.parts and do the DOM changes described above? What is the right "angular way" for this? Or, maybe it is possible to 'intercept' ng-repeat action and do everything there?
You can use ng-class with an 'object' expression.
<i class="fa" ng-class="{'fa-check' : part.name, 'fa-question-circle' : !part.name}">
You can use ng-class and title
<i ng-class="{'fa-check':showFaCheck(part.name), 'fa-question': !showFaCheck(part.name) }" title="{{getTooltip(part.name)}}"/>
Fiddle http://jsfiddle.net/4PYZa/303/

angularjs how set right scope for function?

have this ng-repeat
<li class="tmmenu-admin-tabs-builder-panel-portlet" ng-repeat="question in questions">
<div>
<span class="tmmenu-admin-tabs-builder-panel-portlet-toggler" ng-click="tatbppTogler()">{{{tatbppt}}}</span>
<span class="tmmenu-admin-tabs-builder-panel-portlet-number">{{question.id}}</span>
{{question.text}}
</div>
<div class="tmmenu-admin-tabs-builder-panel-portlet-options" ng-show="showTatbppo">
...
</div>
</li>
I want, for click in "tmmenu-admin-tabs-builder-panel-portlet-toggler" change visibility "tmmenu-admin-tabs-builder-panel-portlet-options" and change text in "tmmenu-admin-tabs-builder-panel-portlet-toggler".
And i write this code for get result:
$scope.tatbppTogler = function(){
$scope.showTatbppo = !$scope.showTatbppo;
if($scope.showTatbppo){
$scope.tatbppt = "-";
}else{
$scope.tatbppt = "+";
}
}
It's works, but changed dom in all "Li", how changed only current (where user click) "li"?
You can do it like this:
<li class=portlet" ng-repeat="question in questions">
<div>
<span class="toggler" ng-click="showTatbppo=!showTatbppo">{{showTatbppo ? "+" : "-" }}</span>
<span class="number">{{question.id}}</span>
{{question.text}}
</div>
<div class="options" ng-show="showTatbppo">
...
</div>
</li>
Working fiddle, with this concept:
http://jsfiddle.net/x1nguaxj/
btw. You have very-very-very long css class names :)
1 way
you can pass this in ng-click="tatbppTogler(this)" and then in function manipulate with this
2 way
you can create custom directive and apply it to your li element and then on this directive bind click to element and listen , and on click function will be triggered your listener and you will have access on this element
You can create an attribute id for each question and then change based on the id of the question you clicked
I would suggest you'd take a look at $index. From the angularjs docs:
iterator offset of the repeated element (0..length-1)
Using this, you can clearly determine the certain div that was clicked on.

Resources