I am new to angular and trying to toggle a class on click only on current link.
But on click it is working on all links. I want it works only on current element.
For which we use (this) in jquery.
script:
var data = '<td id="'+index+'" class="drag drop"><div class="ui-resizable tac"><div class="ui-resizable">' + header[index].description + '<br>' + header[index].name +'</div></div><div id="div'+index+'" class="report-container" style="display:inline-block;float:left;"><ul class="report-list">';
for( var key = 0; key < listTemp.length; key ++){
data+= "<li class='bg-l-grey' ng-class='{ opened: selectedIndex == 0}' style='background:" + listTemp[key].color +"'><span><em class='left'>" + listTemp[key].mpValue + "</em><em class='right'>" + parseInt(listTemp[key].yield) + "</em></span>"+
'<div class="list-swiper bg-black" ng-click="selectedIndex = 0"><span class="swipe-left"></span><span class="swipe-right"></span></div><div class="report-icon-list bg-l-green"><span><i class="cht-sprite"></i></span><span><i class="cht-sprite"></i></span><span><i class="cht-sprite"></i></span></div></li>';
}
data+= '</ul></div></td>';
$scope.openSwap = function($event) {
// body...
var elementParent = $event.currentTarget.parentElement.offsetParent;
angular.element(elementParent).toggleClass("opened");
if ($(elementParent).hasClass("opened")) {
}else {
console.log(false);
}
$event.stopPropagation();
}
I want click event on ".list-swiper" class and class toggle on parent li.
You can toggle a class and use ng-class with this:
<div class="list-swiper bg-black"
ng-class="{ opened: thisElementClicked }"
ng-click="thisElementClicked = true">..</div>
This will add a class 'opened' to the div element when you click it.
You can of course also add the ng-class to the parent, which will add the class on the parent:
<li ng-class="{ opened: thisElementClicked }">
<div class="list-swiper bg-black"
ng-click="thisElementClicked = true">..</div>
</li>
You probably have multiple li elements, where you might want to do this more dynamically:
<ul>
<li ng-class="{ opened: selectedIndex == 0 }">
<div class="list-swiper bg-black"
ng-click="openSwap(0)">..</div>
</li>
<li ng-class="{ opened: selectedIndex == 1 }">
<div class="list-swiper bg-black"
ng-click="openSwap(1)">..</div>
</li>
</ul>
controller:
$scope.openSwap = function (index) {
$scope.selectedIndex = index;
// .. more
}
Even simpler, if you can build the li's dynamically:
$scope.swipers = [
{ title: "first swiper"},
{ title: "second swiper"},
// ..
}
$scope.openSwap = function (index) {
$scope.selectedIndex = index;
// or toggle, depends what you want:
// if ($scope.selectedIndex == index) {
// $scope.selectedIndex = -1;
// } else {
// $scope.selectedIndex = index;
// }
}
view:
<ul>
<li ng-repeat="swiper in swipers"
ng-class="{ opened: selectedIndex == $index }">
<div class="list-swiper bg-black"
ng-click="openSwap($index)">{{ swiper.title }}</div>
</li>
</ul>
"jqLite" (defined on the angular.element page) provides DOM traversal methods like children(), parent(), contents(), find(), next() (but not previous()). There is no selector-like method.
You can try core JavaScript's querySelector, follow link:
https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector.
There is no any $(this) concept in angular what you do in jquery, instead you have to traverse till the element through javascripts querySelector or angular.element(document).find(...) or $document.find()
for documentation find the checkout below link:
https://docs.angularjs.org/api/ng/function/angular.element
Use ng-class to change the class on this particular link.
<ANY class="ng-class: expression;"> ... </ANY>
Related
I have an ng-repeat on my page, and I need to filter the items that are in it. For the purposes of filtering I've included the hidden field above it which contains a key that I need to use.
<div class="filterProductsContainer">
<asp:HiddenField runat="server" ID="FilterKey"/>
<ul class="product_listing_component--results-list">
<li ng-if="isInCategory(product, $event)" ng-repeat="product in filterProducts">
<a href="{{product.link}}">
<img src="{{product.image}}" /></a>
</li>
</ul>
</div>
$scope.isInCategory = function (product, $event) {
console.log(product);
console.log($event);
var filterKey = $($event.target).parent(".filterProductsContainer").find("input[type='hidden'").val();
console.log(filterKey);
var targetProduct = $scope.products[product];
var foundMatch = false;
for (var tag in targetProduct.tags) {
var targetTag = targetProduct.tags[tag];
if (filterKey === targetTag.id) {
foundMatch = true;
}
if (foundMatch) {
break;
}
}
return foundMatch;
}
$event ends up being null, though.
Try using the filter directly in ng-repeat
<li ng-repeat="product in filterProducts | filter: {id: '<FilterKeyValue>'}" >
Where id is the property name of your product object you want use to filter by.
Trying to add a class to an element inside an li item when a function call is made. I can get the correct value outputted, however finding the child <i> is proving difficult. If I could find the correct nested <i> and add the class 'show' that would solve it :)
JS code:
filterMarkers = function(category) {
for (i = 0; i < markers1.length; i++) {
marker = gmarkers1[i];
// If is same category or category not picked
if (marker.category == category || category.length === 0) {
marker.setVisible(true);
// Show the tick icon
$(".filter").find("[data-value='" + category + "']").addClass('show');
}
// Categories don't match
else {
marker.setVisible(false);
}
}
}
HTML code:
<ul class="drop-down">
<li class="filter blue" data-value="" onclick="filterMarkers('');">All <i class="fi-check"></i></li>
<li class="filter yellow" data-value="test-one" onclick="filterMarkers('test-one');">Sales <i class="fi-check"></i></li>
<li class="filter red" data-value="test-two" onclick="filterMarkers('test-two');">Incentives <i class="fi-check"></i></li>
<li class="filter grey" data-value="test-three" onclick="filterMarkers('test-three');">Conferences <i class="fi-check"></i></li>
<li class="filter orange" data-value="test-four" onclick="filterMarkers('test-four');">Team building <i class="fi-check"></i></li>
</ul>
Looking at the filterMarkers method, you
Either want to simply show the category which is passed as argument and hide everything else
Or if no argument is passed then hide everything.
Simplify your code to
filterMarkers = function(category) {
$(".filter").removeClass("show"); //remove show class from all
if( category.length > 0 )
{
$(".filter[data-value='" + category + "']").addClass('show');
}
for (i = 0; i < markers1.length; i++)
{
marker = gmarkers1[i];
marker.category == category || category.length === 0 ? marker.setVisible( true ) : marker.setVisible( false );
}
}
}
$(".filter[data-value='" + category + "']").addClass('show');
The following code works, but I think there's room for improvement. The index check is there because after the first element is removed the next element looks like it has an index of -1, but is actually the previously removed element. Then it iterates again and finds the clicked element and removes it. BUT since the index is -1 on the first go around the wrong group gets deleted.
How do I keep the zombie elements from being iterated on more efficiently? This is in a backbone view with an in page confirmation.Thanks.
EDIT: To add HTML
Group section always has a default group that shouldn't be deleted.
<div class="section-border-top--grey js-favorite-group">
<h4 class="expandable__cta cta--std-teal js-expand-trigger"><span class="icon icon-plus--teal expandable__cta-icon"></span>All Doctors</h4>
<div class="expandable__content js-favorite-doctor-row-container" aria-expanded="true">
<div class="location-section dr-profile">
<div class="section__content js-doctor-row">
<div class="favorite-doctor-manage__row">
DR info
</div>
</div><!--/section__content-->
</div><!--/location-section-->
</div><!--/expandable__content-->
Tag section to remove groups
<div class="js-favorite-doctor-manage-add-remove">
<div class="grid-construct">
<div class="expandable" data-controller="expandable">
<ul class="tag-list js-group-list" tabindex="-1">
<li class="tag tag--teal" >
Lauren's Doctors
<ul class="tag-sub">
<li><button class="tag-icon tag-icon--close-white js-group-remove">Remove group: Lauren's Doctors</button></li>
</ul>
</li>
<li class="tag tag--teal" >
Timmy's Doctors
<ul class="tag-sub">
<li><button class="tag-icon tag-icon--close-white js-group-remove">Remove group: Timmy's Doctors</button></li>
</ul>
</li>
</ul>
</div>
removeGroup: function( evt ) {
var deleteGroup = function() {
if ( $(evt.currentTarget).closest('.tag').hasClass('is-active')){
var clickedTag = $(evt.currentTarget).closest('.tag');
var groupList = this.$el.find('.js-group-list');
var groupTags = groupList.find('.tag');
var index = groupTags.index(clickedTag);
var groupSections = $('.js-favorite-group');
// add one to account for "All" section which is never removed
var groupToRemove = groupSections.eq(index + 1);
console.log(groupToRemove);
var removedGroupName = this.getGroupNameForSection(groupToRemove);
var allDoctors = groupSections.eq(0);
var allDoctorsContainer = allDoctors.find('.js-favorite-doctor-row-container');
if ( index > -1 ){
groupToRemove.find('.js-favorite-doctor-row').appendTo(allDoctorsContainer);
clickedTag.remove();
groupToRemove.remove();
this.updateSectionDropdowns();
this.ariaAlert('Group ' + removedGroupName + ' removed');
this.hideConfirm(evt);
}
}
};
this.showAlert(evt, deleteGroup);
},
showAlert: function (evt, callback) {
that = this;
var clickedTag = '';
clickedTag = $(evt.currentTarget).closest('.tag');
clickedTag.addClass('is-active').attr('data-delete','true');
$('.delete-acct-message').show().focus();
$('.js-remove-yes').on('click', function(evt){
evt.preventDefault();
callback.apply(that);
});
$('.js-remove-no').on('click', function(evt){
evt.preventDefault();
this.hideConfirm(evt);
});
},
I would suggest that you should use custom attributes in your html, this will simplify your javascript logic and make it more effective and efficient.
I have modified your html and javascript to add the support for custom attribute data-doc-group. Have a look at your group sections div here
<div data-doc-group="lauren" class="section-border-top--grey js-favorite-group">
<h4 class="expandable__cta cta--std-teal js-expand-trigger"><span class="icon icon-plus--teal expandable__cta-icon"></span>Lauren's Doctors</h4>
<div class="expandable__content js-favorite-doctor-row-container" aria-expanded="true">
<div class="location-section dr-profile">
<div class="section__content js-doctor-row">
<div class="favorite-doctor-manage__row">
DR info
</div>
</div><!--/section__content-->
</div><!--/location-section-->
</div>
Here are the tags with custom attributes
<li data-doc-group="lauren" class="tag tag--teal">
Lauren's Doctors
<ul class="tag-sub">
<li><button class="tag-icon tag-icon--close-white js-group-remove">Remove group: Lauren's Doctors</button></li>
</ul>
</li>
<li data-doc-group="timmy" class="tag tag--teal">
Timmy's Doctors
<ul class="tag-sub">
<li><button class="tag-icon tag-icon--close-white js-group-remove">Remove group: Timmy's Doctors</button></li>
</ul>
</li>
Here is the javascript to handle this, (this may be a bit buggy, but will give you a general idea)
removeGroup: function(evt) {
this.showAlert(evt, function() {
var $clickedTag = $(evt.currentTarget).closest('.tag'),
dataGroupName,
$groupToRemove,
removedGroupName,
$allDoctors = $('.js-favorite-group').eq(0),
$allDoctorsContainer = $allDoctors.find('.js-favorite-doctor-row-container');
if ($clickedTag.hasClass('is-active')){
dataGroupName = $clickedTag.data('doc-group');
$groupToRemove = $allDoctors.siblings('[data-doc-group="' + docGroupName + '"]');
if ($groupToRemove.length > 0){
$groupToRemove.find('.js-favorite-doctor-row').appendTo($allDoctorsContainer);
$clickedTag.remove();
$groupToRemove.remove();
removedGroupName = this.getGroupNameForSection($groupToRemove);
this.updateSectionDropdowns();
this.ariaAlert('Group ' + removedGroupName + ' removed');
this.hideConfirm(evt);
}
}
});
}
hello i'm trying to get element from the DOM in angular directive.
this element:
click image
i'm trying to get this element by unknow id this is the code:
pass user object:
<dashboard user="user" action="pageSelect(name,pageNumber)"></dashboard>
in templateUrl directive:
<section>
<li id="Dashboard{{$index}}" ng-repeat="dashboard in user.NavigationMenu">
<h3 class="PovDashboard">
<i class="fa fa-tachometer"></i>
{{dashboardName}}
</h3>
<ul class="povPages">
<li ng-repeat="page in dashboard.Pages"> <i class="povIconRight fa fa-angle-double-right"></i></li>
</ul>
</li>
and this is the problem:
scope.$watch('user', function(newValue) {
if (newValue !== undefined) {
console.log(scope.user.NavigationMenu[0].Pages);
var defaultDashboard = scope.user.DefaultDashboardID;
console.log(scope.user);
angular.forEach(scope.user.NavigationMenu,function(value,key){
if(value.ID === defaultDashboard){
console.log(key);
// i tried everything
var s = '#Dashboard' + key;
var e = angular.element.find(s)
//e is empty
console.log(e);
//i'm trying to do
//e.('.povPages').first().css("display","block");
}
})
}
});
thanks in advance
You are not using the jqLite wrapper angular.element() syntactically correct, i guess you should try with this:
angular.element(s).find('ul').css('display', 'block');
If you are not using jQuery then .find() will have a lookup at tagnames only.
From the docs:
find() - Limited to lookups by tag name
Or better do it with angular way with ng-show/ng-hide:
<ul class="povPages" data-ng-show='isVisible'>
initialize $scope.isVisible = false;now in the .$watch() do this:
scope.$watch('user', function(newValue) {
if (newValue != undefined) {
console.log(scope.user.NavigationMenu[0].Pages);
scope.isVisible = newValue != undefined ? true : false;
console.log(scope.user, scope.isVisible);
}
});
A sample demo:
angular.module('demoapp', []).controller('demoCtrl', ['$scope', '$timeout',
function($scope, $timeout) {
$scope.arr = [{
text: "one"
}, {
text: "two"
}];
$scope.isVisible = false;
$timeout(function() {
$scope.isVisible = true;
}, 2000);
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app='demoapp' ng-controller='demoCtrl'>
<div ng-repeat="obj in arr">
<h1>see if list is visible == {{isVisible}} {{obj.text}}</h1>
<ul ng-show='isVisible'>
<li>should be visible after value change. {{obj.text}}</li>
</ul>
</div>
</div>
<ul class="listing listing-sm small" ng-class="{'divider': (model.selections | filter:filter).length > 0}">
<li ng-repeat="selection in model.selections | filter:filter" ng-class="{highlight: selection.on}">
Is there a better way to add the class on the ul without running the data through the filter 2x (on the ul and the ng-repeat)?
You can create the filter in a callback function and check the length their and change a flag accordingly to the result.
<ul class="listing listing-sm small" ng-class="{'divider':hasResults}">
<li ng-repeat="selection in manualFilter(model.selections)" ng-class="{highlight: selection.on}">
And in the js:
$scope.manualFilter = function(selections) {
var result = $filter('filter')(selections);
if (result.length > 0 ) {
$scope.hasResults = true;
} else {
$scope.hasResults = false;
}
}
You can use something like $index and a variable called $scope.selected and use
ng-class = "'highlight': $index === selected"