Remove class 'selected' from another function - angularjs

I have an ng-class function which add the class 'Selected' through a toggle function. I want to remove ALL the items classes that have this 'Selected' class when this function runs.
controller.js
$scope.addItemToggle = function(item) {
item.selected = !item.selected;
if (item.selected) {
$scope.items.push({
itemName: item.itemName,
itemIcon: item.itemIcon,
});
} else {
var index = $scope.items.indexOf(item);
$scope.items.splice(index, 1);
}
};
view.html
<ul class="outfit-icons row">
<li class="outfit-button col-33" ng-repeat="item in clothing" ng-class="{'selected':item.selected}" ng-click="addItemToggle(item)">
<div class="item-tick">
<i class="ion-android-done"></i>
</div>
</li>
</ul>

You can pass an index parameter to your function :
<ul class="outfit-icons row">
<li class="outfit-button col-33" ng-repeat="item in clothing" ng-class="{'selected':item.selected}" ng-click="addItemToggle(item, $index)">
<div class="item-tick">
<i class="ion-android-done"></i>
</div>
</li>
</ul>
$scope.addItemToggle = function(item, index) {
$scope.items.forEach(function (item, i) {
if (i !== index) {
item.selected = false;
}
});
if (item.selected) {
$scope.items.push({
itemName: item.itemName,
itemIcon: item.itemIcon,
});
} else {
var index = $scope.items.indexOf(item);
$scope.items.splice(index, 1);
}
};

Related

How to Expand a Default Angular UI Tree Node

I have the following markup:
<div class="modal fade" id="locationSearchModal" tabindex="-1" role="dialog">
<div class="modal-dialog narrow-modal" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Search for Locations</h4>
</div>
<div class="modal-body">
<div class="tree-container">
<section>
<h2>Browse for Locations</h2>
<div ui-tree="" data-drag-enabled="false" id="tree-root">
<ul ui-tree-nodes="" ng-model="data">
<li ng-repeat="item in data" ui-tree-node="" collapsed="!item.ItemsRetrieved" ng-include="item.Place || item.$hashkey == undefined ? 'parent_items_renderer' : 'terminal_item_renderer' " ></li>
</ul>
</div>
<script type="text/ng-template" id="parent_items_renderer">
<div ui-tree-handle class="tree-node tree-node-content" ng-class="{'tree-node-open': !collapsed}" ng-click="toggle(item); convertObjs(item)">
<i class="fa fa-caret-right" ng-class="{'fa-caret-right': collapsed, 'fa-caret-down': !collapsed}"></i>
<i class="fa fa-map-marker" ng-class="{'text-blue': !collapsed}"></i>
<span class="" ng-bind-html="item.PlaceName"></span>
</div>
<ul ng-if="item.Place != null" ui-tree-nodes ng-model="item.Place" ng-class="{hidden: collapsed}">
<li ng-repeat="item in item.Place" ui-tree-node collapsed="!item.ItemsRetrieved" ng-include="item.Place ? 'parent_items_renderer' : 'terminal_item_renderer' " on-finish-render="ngRepeatFinished"> </li>
</ul>
</script>
<script type="text/ng-template" id="terminal_item_renderer">
<div ui-tree-handle class="tree-node tree-node-content" ng-class="{'tree-node-open': !collapsed}" ng-click="addLocation(item)">
<a href title="Add Location"><span class="" ng-bind-html="item.PlaceName"></span></a>
</div>
</script>
</section>
</div>
</div>
</div>
</div>
</div>
The JSON data object that contains the location data is an hierarchical collection of Places:
{
"PlaceHierarchy":{
"Places":{
"Place":{
"PlaceID":"1000",
"PlaceTypeID":"5",
"PlaceName":"Company",
"AbbrName":"Company",
"Place":[
{
"PlaceID":"2000",
"PlaceTypeID":"4",
"PlaceName":"Region",
"AbbrName":"ThePlace",
"Place":[
{
"PlaceID":"3000",
"PlaceTypeID":"3",
"PlaceName":"SubRegion",
"AbbrName":"TheSubPlace",
"Place":[
{
"PlaceID":"4000",
"PlaceTypeID":"2",
"PlaceName":"SubSubRegion",
"AbbrName":"TheSubSubPlace",
"Place":[
{
"PlaceID":"5000",
"PlaceTypeID":"1",
"PlaceName":"Building",
"AbbrName":"Building",
"Place":[
{
"PlaceID":"5001",
"PlaceTypeID":"6",
"PlaceName":"Lobby",
"AbbrName":"Lobby"
},
{
"PlaceID":"5002",
"PlaceTypeID":"6",
"PlaceName":"Lobby 2",
"AbbrName":"Lobby2"
}
]
}
]
}
]
}
]
}
]
}
}
}
}
When I get that JSON back from the API, I need to process the data to make sure that all nodes are arrays. I do it like this:
$scope.processLocationNodes = function (nodes) {
for (var node in nodes) {
if (angular.isArray(node)) {
$scope.processLocationNodes(node);
} else {
$scope.convertObjs(node);
};
}
};
$scope.convertObjs = function (item) {
angular.forEach(item.Place, function (items) {
if (items != undefined && !angular.isString(items)) {
if (items.Place && !angular.isArray(items.Place)) {
var PlaceObj = items.Place;
items.Place = [];
items.Place.push(PlaceObj);
}
}
});
};
Now, when the modal is shown, the data properly displays and the tree works as expected. The only problem is, I want to default the tree to expand to the node of the Default Place of the user. I do that by the following logic:
The onFinishRender directive (debugging the code shows that this is hit):
app.directive('onFinishRender', function ($timeout) {
return {
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit(attr.onFinishRender);
});
}
}
}
});
The ngRepeatFinished function is as follows:
$scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
var rootScope = $scope.getRootNodesScope();
if (rootScope != undefined) {
rootScope.collapseAll();
$scope.expandNode($scope.defaultPlace);
}
});
$scope.getRootNodesScope = function() {
return angular.element(document.getElementById("tree-root")).scope().$nodesScope.childNodes()[0];
}
$scope.expandNode = function(nodeId) {
// We need to get the whole path to the node to open all the nodes on the path
var parentScopes = $scope.getScopePath(nodeId);
for (var i = 0; i < parentScopes.length; i++) {
parentScopes[i].expand();
}
};
$scope.getScopePath = function (nodeId) {
return $scope.getScopePathIter(nodeId, $scope.getRootNodesScope(), []);
};
$scope.getScopePathIter = function(nodeId, scope, parentScopeList) {
if (!scope) return null;
var newParentScopeList = parentScopeList.slice();
newParentScopeList.push(scope);
if (scope.$modelValue && scope.$modelValue.id === nodeId) return newParentScopeList;
var foundScopesPath = null;
var childNodes = scope.childNodes();
for (var i = 0; foundScopesPath === null && i < childNodes.length; i++) {
foundScopesPath = $scope.getScopePathIter(nodeId, childNodes[i], newParentScopeList);
}
return foundScopesPath;
};
Now, here's what my problem is:
First of all at the angular.element(document.getElementById("tree-root")).scope().$nodesScope.childNodes()[0] code, "childNodes()" is empty. No childNodes exist at all. Thus, the code has nothing to collapse or expand. I don't know why the childNodes collection is empty.
Second, once I figure that out, I can see what the actual NodeId is for a specific node and then be able to expand the tree to that node using the $scope.defaultPlace object.
Essentially, I just need to know why the childNodes collection is empty.

how to implement ng-show right way?

can someone check my code and tell me how to make it in right way?
it works but i don't think this is the right
if i would have 20 sub menus,i would need to create 20 functions,which is definitely wrong
thank you in advance
<ul class="menu-top">
<li ng-click="menu2show()">drinks</li>
<li ng-click="menu1show()">food</li>
<li ng-click="menu3show()">desserts</li>
</ul>
<div id="menu-content" ng-controller="MenuCtrl">
<div class="menu1" ng-show="show1" >
<div class="item" ng-repeat="item in menu.menu1">
</div>
</div>
<div class="menu2" ng-show="show2" >
<div class="item" ng-repeat="item in menu.menu2">
</div>
</div>
<div class="menu3" ng-show="show3" >
<div class="item" ng-repeat="item in menu.menu3">
</ul>
</div>
</div>
</div>
var app = angular.module('App', []);
app.controller('MenuCtrl', function($scope) {
$scope.menu = {
menu1:[
{"name":"item1", "price":"1", "desc":"aaa"},
{"name":"item2", "price":"2", "desc":"bbb"},
{"name":"item3", "price":"3", "desc":"ccc"},
],
menu2:[
{"name":"item8", "price":"6", "desc":"zzz"},
{"name":"item9", "price":"4", "desc":"xxx"},
{"name":"item10", "price":"2", "desc":"sss"},
],
menu3:[
{"name":"item15", "price":"3", "desc":"mmmm"},
{"name":"item16", "price":"1", "desc":"nnn"},
{"name":"item17", "price":"5", "desc":"bbb"},
]};
$scope.show1 = true;
$scope.menu1show = function(){
$scope.show1 = true;
$scope.show2 = false;
$scope.show3 = false;
}
$scope.menu2show = function(){
$scope.show1 = false;
$scope.show2 = true ;
$scope.show3 = false;
}
$scope.menu3show = function(){
$scope.show1 = false ;
$scope.show2 = false ;
$scope.show3 = true ;
}
});
You can make a scope variable to capture the menu that you wish to display.
$scope.showMenu = 1;
Then for each menu:
<div class="menu2" ng-show="showMenu === 2" >
...
<div class="menu1" ng-show="showMenu === 1" >
and so on.
And for the click:
<li ng-click="showMenu = 2">drinks</li>
and so on.

How can I use filter in more than one ng-repeat?

HTML Code This is used for display images in grid.
I used this link -- http://codepen.io/pulkitsinghal/pen/JjmED/
In this i used 5 ng-repeat tags but i got errors on filter ng-repeat="row in f.images | inSlicesOf:2"
<div class="list itemnew card" ng-repeat="group in groups">
<ion-item class="item item-icon-right" ng-click="toggleGroup(group)" ng-class="{active: isGroupShown(group)}" style="">
<i class="ion-chevron-right pull-right" ng-class="isGroupShown(group) ? 'ion-chevron-down' : 'ion-chevron-right'" style="float:right;"><input type="hidden" ng-model="group.menu_name"></i> {{group.menu_name}}
<div ng-switch on="group.menuid">
<!--Facilitites-->
<div ng-switch-when="8">
<ion-item class="item-accordion item ng-binding ng-hide " ng-show="isGroupShown(group)" style="">
<div class="item bdr-none blue-light" style="margin-top:25px !important;">
<div ng-repeat="facility in group.facilities">
<div ng-repeat="f in facility">
<h2 class="padding-left">{{f.facilities_name}}</h2>
<div class="row" ng-repeat="row in f.images | inSlicesOf:2">
<div class="col col-50" ng-repeat="item in row">
<img src="{{item.img_name}}" class="col col-30" ng-click="showImage('{{item.img_name}}')" />
</div>
</div>
</div>
</div>
</div>
</ion-item>
</div>
</div><!--Switch-->
</ion-item>
</div>
<!-- end ngRepeat: item in group.items -->
Controller
This in controller where i put my filter.
var app = angular.module('test', ['ionic']);
app.filter('inSlicesOf', ['$rootScope',
function ($rootScope) {
makeSlices = function (items, count) {
if (!count)
count = 3;
if (!angular.isArray(items) && !angular.isString(items)) return items;
var array = [];
for (var i = 0; i < items.length; i++) {
var chunkIndex = parseInt(i / count, 10);
var isFirst = (i % count === 0);
if (isFirst)
array[chunkIndex] = [];
array[chunkIndex].push(items[i]);
}
if (angular.equals($rootScope.arrayinSliceOf, array))
return $rootScope.arrayinSliceOf;
else
$rootScope.arrayinSliceOf = array;
return array;
};
return makeSlices;
}]);
app.controller('AboutUsCtrl', function ($scope, $http, $ionicModal) {
$scope.groups = [];
if (window.localStorage.getItem("about") !== null) {
if (window.localStorage.getItem("about") !== "undefined") {
$scope.groups = JSON.parse(window.localStorage.getItem("about"));
}
}
$http.post("json")
.success(function (response) {
if (response.about === undefined) {
if (window.localStorage.getItem("about") !== "undefined") {
$scope.groups = JSON.parse(window.localStorage.getItem("about"));
}
} else {
$scope.groups = response.about;
window.localStorage.removeItem("about");
window.localStorage.setItem("about", JSON.stringify(response.about));
}
}).error(function (data) {
if (window.localStorage.getItem("about") !== "undefined") {
$scope.groups = JSON.parse(window.localStorage.getItem("about"));
}
});
$scope.toggleGroup = function (group) {
if ($scope.isGroupShown(group)) {
$scope.shownGroup = null;
} else {
$scope.shownGroup = group;
}
};
$scope.isGroupShown = function (group) {
return $scope.shownGroup === group;
};
});
Error in console
For the preference purpose
Error: [$rootScope:infdig] errors.angularjs.org/1.4.3/$rootScope/infdig?p0=10&p1=%5B%5B%7B%22ms…22%3A%22http%3A%2F%2Fkbs-test.com%2Fimages%2Fpages%2Fimg13.jpg%22%7D%5D%5D
at Error (native)
at 127.0.0.1:58889/http-services/emulator-webserver/ripple/userapp/x/C/…-a621-2128fb7dbab1/platforms/ios/www/js/angular/ionic.bundle.min.js:37:416
at n.$digest (127.0.0.1:58889/http-services/emulator-webserver/ripple/userapp/x/C/…-a621-2128fb7dbab1/platforms/ios/www/js/angular/ionic.bundle.min.js:164:96)
at n.$apply (127.0.0.1:58889/http-services/emulator-webserver/ripple/userapp/x/C/…a621-2128fb7dbab1/platforms/ios/www/js/angular/ionic.bundle.min.js:166:269)
at HTMLBodyElement. (127.0.0.1:58889/http-services/emulator-webserver/ripple/userapp/x/C/…a621-2128fb7dbab1/platforms/ios/www/js/angular/ionic.bundle.min.js:137:115)
at HTMLBodyElement.Gf.c (127.0.0.1:58889/http-services/emulator-webserver/ripple/userapp/x/C/…-a621-2128fb7dbab1/platforms/ios/www/js/angular/ionic.bundle.min.js:66:217)
at n (127.0.0.1:58889/http-services/emulator-webserver/ripple/userapp/x/C/…-a621-2128fb7dbab1/platforms/ios/www/js/angular/ionic.bundle.min.js:22:384)
at t (127.0.0.1:58889/http-services/emulator-webserver/ripple/userapp/x/C/…-a621-2128fb7dbab1/platforms/ios/www/js/angular/ionic.bundle.min.js:22:216)
at HTMLDocument.l (127.0.0.1:58889/http-services/emulator-webserver/ripple/userapp/x/C/…a621-2128fb7dbab1/platforms/ios/www/js/angular/ionic.bundle.min.js:22:1451)

AngularJS determine filter in controller

How would I go about setting the filter property on an ng-repeat dynamically?
Here is my template...
<div class="list-group">
<div ng-repeat="article in articles | activeFilter">
<a href="#" class="list-group-item">
<h3 class="list-group-item-heading">{{ article.title }}</h3>
<h4 class="list-group-item-text">{{ article.author }}</h4>
<p class="list-group-item-text">"{{ article.blurb }}"</p>
</a>
</div>
</div>
Where "activeFilter" is a property I want to set via the controller...
...
$scope.activeFilter = 'someFilterType'
...
And the filter looks like this...
.filter('someFilterType', function () {
return function (items) {
var rv = [];
for (var p in items) {
if (items[p].myFilterProp === false)
rv.push(items[p]);
}
return rv;
}
})
I would think I could dynamically change the ng-repeat's filter in this way, but it doesn't seem to be working and I'm not sure why.
Try something like this:
HTML
ng-repeat="article in articles | filter:activeFilter[filter]"
Controller:
$scope.filter = "name1";
$scope.activeFilter = {
name1: $scope.someFilterFunction,
name2: $scope.someOtherFilter,
name3: $scope.andAnother
};
$scope.someFilterFunction = function() {
var rv = [];
for (var p in items) {
if (items[p].myFilterProp === false)
rv.push(items[p]);
}
return rv;
};

jQuery sortable not working

I have a jquery accordion with selectable lists inside. When the user clicks an item, it appears in their selected items list, which is sortable. There are a number of columns that appear in their list as default columns, and each item selected shows up as green in the accordion.
My issue is that line items with two words in the sortable list are not sortable, but items with one word are. I cannot figure out why. Any thoughts?
Here's my fiddle: http://jsfiddle.net/kmbonin82/NkgC2/9/
HTML:
<h3>List 1</h3>
<ul class="list">
<li id="Country">Country</li>
<li id="Region">Region</li>
<li id="Location_Name">Location Name</li>
<li id="Location_Start">Location Start</li>
</ul>
<h3>List 2</h3>
<ul class="list">
<li id="Contract_Start">Contract Start</li>
<li id="Contract_Status">Contract Status</li>
<li id="Contract">Contract</li>
</ul>
<p id="feedback">
<span>You've selected items:</span>
<ul id="select-result">
<li id="Region">Region</li>
<li id="Location Name">Location Name</li>
<li id="Country">Country</li>
<li id="Contract Status">Contract Status</li>
</ul>
</p>
JS:
$(function () {
$(".list").selectable({
stop: function () {
var result = $("#select-result");
$(".ui-selected", this).each(function () {
$(this).css('background-color', '#669966');
$(this).css('color', '#FFFFFF');
result.append('<li id="' + $(this).text() + '">' + $(this).text() + '</li>');
sortColumns();
});
}
});
sortColumns();
});
$(function () {
$("#accordion").accordion({
collapsible: true,
autoHeight: false
});
});
$(function () {
$("#select-result li").each(function (index) {
var thisID = $(this).attr('id');
thisID = thisID.replace(/ /g, '_');
document.getElementById(thisID).style.background = '#669966';
document.getElementById(thisID).style.color = '#FFFFFF';
sortColumns();
});
});
function sortColumns() {
$(function () {
$("#select-result")
.sortable({
handle: ".handle",
over: function () {
removeIntent = false;
},
out: function () {
removeIntent = true;
},
beforeStop: function (event, ui) {
if (removeIntent == true) {
var thisID = ui.item.text();
thisID = thisID.replace(/ /g, '_');
ui.item.remove();
document.getElementById(thisID).style.background = '#FFFFFF';
document.getElementById(thisID).style.color = '#000000';
}
}
})
.find("li")
.addClass("ui-corner-all")
.prepend("<div class='handle'><span class='ui-icon ui-icon-carat-2-n-s'></span></div>");
});
}
The 'Location Name' and the 'Contract Status' are not sortable because their id values are wrong. You have space between them.
<li id="Location Name">Location Name</li>
<li id="Contract Status">Contract Status</li>
Updated Demo: http://jsfiddle.net/NkgC2/10/
Bonus:
a) the way you are pre-pending the div is not a right way. If you see your html code, after each item you select it adds an extra div for each list item
b) Instead of calling sortable() function couple times (it get calls 3 times before even selecting any item. ) use jquery 'on' method to bind api to non-existing elements.

Resources