Angular JS: Sort Grid Contents based on Dropdown Selection - angularjs

I have a drop down button in my headerCellTemplate that looks like this
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle"
data-toggle="dropdown">
<b>Value</b><span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" style="position:fixed;top:inherit;left:320px;">
<li>H</li>
<li>M</li>
<li>L</li>
</ul>
</div>
On click it is it suppose to sort the ng grid contents. I have written the code that can sort the grid contents from H-M-L. the function looks like this
var result = 1;
var test="HML";
function impSortFn(a, b) {
a=test.indexOf(a);
b=test.indexOf(b);
if (a == b) return 0;
if (a < b) return -1;
return result;
}
And the column Defs looks like this
columnDefs: [
{
field:'dt', displayName:'Date', width:'***',
cellFilter:'date:\"dd-MMM-yyyy\"', headerClass:'grad1',
cellTemplate:'<div><center>{{row.getProperty(\'dt\')|dateformat}}</center></div>'
},
{
field:'dt', displayName:'Time', width:'**',
cellFilter:'date:\"HH:mm:ss\"', headerClass:'grad1',
cellTemplate:'<div><center>{{row.getProperty(\'dt\')|timefilter}}</center></div>'
},
{
field:'rl', displayName:'Impact',width:'80px',
sortFn:impSortFn, headerClass:'grad1', headerCellTemplate:"impactHeader.html",
cellTemplate:'<div class="ngCellText" ng-class="col.colIndex()"><center><img ng-src="{{row.getProperty(\'rl\') | dateformat1}}"</img></center></div>'
}
]
Can any one please tell me how can I modify the function such that it returns only M values when M is selected from the drop down. and same for H and L.

In order to help in some way, i am posting a SO answer which is an alternative way of solving your problem.
It sure has better practices.
Have a look at this SO question.
In this question, ng-change is added to your element which is fully doable. According to a new value, you bind your grid again..
I used it in a project of mine. Here it is..
<input maxlength="34" type="text" ng-model="pollInfo.companyName" ng-change="updateIframe()" class="has-success form-control pull-left" placeholder="Anket Logo Yazısı" required id="companyName">
Ang get the change in controller
$scope.updateIframe = function() {
var data=new Object();
data.questions=$scope.questions;
data.pollInfo=$scope.pollInfo;
document.getElementById('iframe').contentWindow.updatedata(data);
};
You can do like this. In your method bind your grid. Again, this is not a best practice.
The best practice is that you do with $filter. But I need more info for your example to solve it.

Related

dynamically change options in dropdown list in angular js

i tried to create dynamically changing dropdown list in angularJS
angulars.js
var option1Options = ["Class","Category","Option","Question","Group"];
var option2Options = [["Group","ProductModel"],
["Class","ProductModel"],
["Class","Group","ProductModel"],
["Group","ProductModel"],
["ProductModel"]];
$scope.myCtrl= function()
{
$scope.options1 = option1Options;
$scope.options2 = [];
$scope.getOptions2 = function(){
var key = $scope.options1.indexOf($scope.child);
$scope.options2 = option2Options[2];
};
}
page.html
<div id="CreateChild" ng-controller="myCtrl">
<select ng-model="child" ng-options="option for option in options1" ng-change="getOptions2()">
</select>
<select ng-model="parent" ng-options="option for option in options2">
</select>
</div>
in angulars.js i was unable to get the index of first dropdown list array. the value of key is assigned as -1 and the option2 is assigned as undefined.
can any one help me with this
I did a small workaround for this requirement, though it is not a straight answer, I believe this would help you...
Add this to your controller...
$scope.getOptions1Idx = function(){
var mySelectedOption = $scope.child;
var i = 0;
for(i=0;i< option1Options.length;i++){
if(option1Options[i]==mySelectedOption){
break;
}
}
return i;
}
and change your getOptions2 function as follows
$scope.getOptions2 = function(){
$scope.options2 = option2Options[getOptions1Idx()];
};
This can be done in much better fashion by avoiding for loop provided if you choose to change your array structure with predefined index some thing like var option1Options = [{id:0,option:"Class"},{id:1,option:"Category"},{id:2,option:"Option"},{id:3,option:"Question","Group"}];
Had a very similar problem with this. In terms of styling I found my way around it by creating a list instead of a select option
<div class='btn-group'>
<button class='form-control col-md-3' data-toggle='dropdown'>
{{value}} <span class='caret'></span>
</button>
<ul class='dropdown-menu'>
<li ng-repeat='type in callType' class='col-md-3'>
<a href='#' ng-click='select(type)'>{{type.name}}</a>
</li>
</ul>
</div>
Then the controller is used to take in the objects, call a method to change each object and then set a default for the drop down list. You can see it at the link below.
http://plnkr.co/edit/nwXmMif8vjj92pQmalb2

Delete a record in NG-repeat protractor

So I'm doing e2e test with protractor and angular,
My first test was adding an element to the list,
Now I'm trying to delete it, and I'm having trouble doing so
So this is what I need to do:
Find the name of the record I want to delete
click on the trashcan icon of that same row and delete it
press ok on the pop up window that appears
Try as much as possible to avoid the use of By.css and prefer everything related to angular( byBinding, model, etc) . This is because this part of the app migh eventually change, hence I will have to redo all this cases.
HTML:
...
<div class="list-group-item ng-scope" ng-repeat="item in teamList">
<span class="glyphicon glyphicon-user"></span>
<span ng-bind="item.name" class="memberName ng-binding">nuevo Team</span>
<a ng-click="editTeam(item._id)" class="hand-cursor">
<span class="glyphicon glyphicon-edit memberRemoveBotton"></span>
</a>
<a ng-confirm-click="Would you like to delete this item?" confirmed-click="deleteTeam(item._id)" class="hand-cursor">
<span class="glyphicon glyphicon-trash memberRemoveBotton"></span>
</a>
</div>
JS:
describe('Testing delete Item',function() {
it('Should delete the Item that just got Inserted',function() {
element(by.css('a[href="#!/item-create"]')).click(); //Opens up the Item dashBoard
element.all(by.repeater('item in itemList')).then(function(table) {
table.element(by.binding('item.name')).each(function(names) {
console.log('the names',names.getText());//I'm trying to find the name of the item that just got inserted
// is there like a nested chaining of elements in here ??
});
});
});
});
Any hints on how to solve this are appreciated
describe('Testing delete Item',function() {
it('Should delete the Item that just got Inserted',function() {
// Assume you know the name of the item you want to delete.
var nameToDelete = 'some name';
// Get the row that has the name by using filter.
element.all(by.repeater('item in itemList')).filter(function(row){
return row.element(by.css('.memberName')).getText().then(function(name){
return name === nameToDelete;
});
})
// Now you should have one row.
.get(0)
// Get the row and click find the remove button.
.element(by.css('.memberRemoveBotton'))
.click();
// Make sure it was deleted.
var names = $$('.list-group-item .memberName').getText();
expect(names).not.toContain(nameToDelete);
});
});
Let me know if it works.
Thank's Andres your answer helped me sort out some doubts I was having.
Anyway here is the answer, one of the most tedious part was the popUp window, let's hope it wont brake later on
it('Should delete the Team that just got Inserted',function() {
element(by.css('a[href="#!/team-create"]')).click(); //Opens up the Team dashBoard
element.all(by.repeater('item in teamList')).filter(function(row) {
return row.element(by.css('.memberName')).getText().then(function(name) {
return name === teamName;
});
}).first().element(by.css('.glyphicon-trash')).click();
testHelper.popUpHandler(ptor);
element.all(by.css('.list-group-item .memberName')).each(function(list) {
expect(list.getText()).not.toContain(teamName);
});
});

How Do I Move Objects Inside An ng-Repeat on Button Click?

I have a nifty list of items in an ng-repeat with an up and down button on each. I just want the up button to move the list item up one place and the down button should move it down one place.
The problem is that I get an error saying "Cannot read property 'NaN' of undefined."
It seems "position" is undefined on the second line. What can I do to fix that?
Heres the javascript I'm working with (thanks to Rishul Matta):
$scope.moveUp = function(ind, position) {
$scope.temp = $scope.list[position - 1];
$scope.list[position - 1] = $scope.list[position];
$scope.list[position = temp];
};
Here's my HTML:
<ul>
<li class="steps" ng-repeat="step in selectedWorkflow.Steps track by $index" ng-class="{'words' : step.Id != selectedStep.Id, 'selectedWords' : step.Id == selectedStep.Id}" ng-model="selectedWorkflow.Step" ng-click="selectStep(step, $index); toggleShow('showSubStep'); toggleShow('showEditBtn')">
{{step.Name}}
<input class="orderUpBtn" type="button" ng-click="moveUp($index, step)" style="z-index:50" value="U" />
<input class="orderDownBtn" type="button" style="z-index:50" value="D" />
</li>
</ul>
Thanks!
Thanks for posting this question (+1) and the answer jtrussell (+1). I wanted to share what I believe to be a more re-usable/modular answer for other folks (inspired by odetocode.com post).
For the HTML, jtrussell's code is perfect because he fixed/simplified everything. For a better user experience I just added ng-disabled for the first/last elements.
HTML:
<ul ng-controller="DemoCtrl as demo">
<li ng-repeat="item in demo.list">
{{item}}
<button class="move-up"
ng-click="listItemUp($index)"
ng-disabled="$first">
Move Up
</button>
<button class="move-down"
ng-click="listItemDown($index)"
ng-disabled="$last">
Move Down
</button>
</li>
</ul>
For the JS, Notice the moveItem() function which I believe to be more re-usable. You can use this function for other drag+drop swapping functionality as well.
JS within Controller (tested on Angular 1.3.15):
// Move list items up or down or swap
$scope.moveItem = function (origin, destination) {
var temp = $scope.list[destination];
$scope.list[destination] = $scope.list[origin];
$scope.list[origin] = temp;
};
// Move list item Up
$scope.listItemUp = function (itemIndex) {
$scope.moveItem(itemIndex, itemIndex - 1);
};
// Move list item Down
$scope.listItemDown = function (itemIndex) {
$scope.moveItem(itemIndex, itemIndex + 1);
};
I hope it is helpful to someone out there. Thanks SO community!
A simple list with up/down buttons is pretty straightforward, here's some rough generic code. The ngRepeat directive will honor the order of items in your array so moving things around the view is just a matter of moving them in the array itself.
view:
<ul ng-controller="DemoCtrl as demo">
<li ng-repeat="item in demo.list">
{{item}}
<button ng-click="demo.moveUp($index)">up</button>
<button ng-click="demo.moveDown($index)">down</button>
</li>
</ul>
controller:
app.controller('DemoCtrl', function() {
this.list = list = ['one', 'two', 'three', 'four'];
this.moveUp = function(ix) {
if(ix > -1 && ix < list.length - 1) {
var tmp = list[ix+1];
list[ix+1] = list[ix];
list[ix] = tmp;
}
};
this.moveDown = function(ix) {
// similar...
};
});
There were a few strange items in your code (for example did you mean $scope.list[position] = temp; when you wrote ($scope.list[position = temp];), my example isn't perfect but it should get you going on the right path. Here's the full working demo: http://jsbin.com/vatekodeje, note that in my code I use "up" to mean increasing index rather than toward the top of the page.
Also in your controller you use position as an index (it's not clear that it should be) and make reference to, presumably, an array called $scope.list when in your view you use selectedWorkflow.Steps. Maybe your $scope.list and selectedWorkflow.Steps are meant to be the same thing?

Change Single Button Color from ngRepeat generated button list

I'm using ngRepeat to generate four buttons. Whenever I click one of the buttons, I want to change its color and also execute a function (for now, I'm just using console.log for sake of simplicity). If I click on another button, I want to change its color while reverting the previous button back to its original color.
I have a couple of issues - the first is that I can't seem to get ng-click to accept two commands (the first being the console.log function and the second being the instruction to change the button color). The other issue is that if I take out the console.log function, I end up changing all of the buttons when I click on one.
Any ideas? Here's the plunkr: http://plnkr.co/edit/x1yLEGNOcBNfVw2BhbWA. You'll see the console.log works but the button changing doesn't work. Am I doing something wrong with this ng-click?
<span class="btn cal-btn btn-default" ng-class="{'activeButton':selectedButt === 'me'}" ng-click="log(element);selectedButt = 'me'" data-ng-repeat="element in array">{{element}}</span>
You can create a simple function in your controller which handles this logic:
$scope.selectButton = function(index) {
$scope.activeBtn = index;
}
Then, you can simply check in your template if the current button is active:
<span class="btn cal-btn btn-default" ng-class="{true:'activeButton'}[activeBtn == $index]" ng-click="selectButton($index);" ng-repeat="element in array">{{element}}</span>
I also changed your plunkr
You may convert your element list from string array to object array first.
$scope.array = [
{"name":"first", "checked":false},
{"name":"second", "checked":false},
{"name":"third", "checked":false},
{"name":"fourth", "checked":false}
];
And your log function need to change to:
$scope.log = function(element) {
console.log(element.name);
angular.forEach($scope.array, function(elem) {
elem.checked = false;
});
element.checked = !element.checked;
}
Then, in your HTML:
<button class="btn cal-btn"
ng-repeat="element in array"
ng-click="log(element)"
ng-class="{activeButton: element.checked, 'btn-default': !element.checked}"
>{{element.name}}</button>
Please see the updated plunker here.

angularjs - resetting li after ngrepeat

I want to flow different data through a user clickable ul but I can't reset the state of the li's which have the isactive style set. Stripping down to bare minimum to demonstrate the input box takes two numbers separated by '-', the first is the number of clickable boxes, the second is the number of unclickable boxes at the beginning.
Note when new input is sent the li's that are currently active remain active. I want to reset the li's to inactive. [ note: trying to do this without jQuery to learn "The Angular Way". I have a pure jQuery version of this ]. angular.copy has not worked (though that could be ignorance)
I'm starting to think this might have to go but I'm keeping the graphic representation exclusively in the .html:
html
<div ng-controller="BoxScreen">
<input type="text" ng-model="inbox" />
<button ng-click="getBox()" /></button>
<div>
<br />
<h2>{{dys}}, {{dst}}</h2>
<div>
<ul class="smallbox">
<li data-ng-repeat="s in skip"> </li>
<li data-ng-repeat="d in ar" ng-class="{'button': !isActive, 'button active': isActive}" ng-init="isActive = false" ng-click="isActive = !isActive; clickMe(d)">{{d}}</li>
</ul>
</div>
</div>
</div>
javascript
angular.module('myApp', [])
.controller('BoxScreen', ['$scope', function($scope) {
$scope.getBox = function() {
indat = $scope.inbox.split('-');
$scope.dys = indat[0];
$scope.dst = indat[1];
$scope.ar = [];
$scope.skip = [];
for(var s=0; s < $scope.dst; s++) {
$scope.skip.push(s);
}
for(var d=1; d <= $scope.dys; d++) {
$scope.ar.push(d);
}
}
$scope.clickMe = function(did) {
//
}
}]);
I believe your problem is related to ng-repeat creating new child scopes for the child elements it attaches to the DOM. When you expand the list with new elements, ng-repeat doesn't actually destroy the old elements (as long as they're unchanged, as is true in your case), but reuse them. See more here.
The way you have designed your structures on the scope seems very messy to me. A better approach is to create all the data beforehand, and not introduce all the logic in the HTML.
Example:
<li data-ng-repeat="d in ar.items" ng-class="{'button': !d.isActive, 'button active': d.isActive}" ng-click="ar.toggle(d)">{{d.text}}</li>
where ar here is an object:
$scope.ar = {
items: [
{
text: '1',
isActive: false
},
more items...
],
toggle: function(d) {
d.isActive = !d.isActive;
}
}
This way you have access to the data in other places as well, and not some hidden away variables set on the child scope.

Resources