dynamically change options in dropdown list in angular js - angularjs

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

Related

ngRepeat doesn't refresh rendered value

I'm having an issue with ngRepeat :
I want to display a list of students in two different ways. In the first one they are filtered by group, and in the second they are not filtered.
The whole display being quite complex, I use a ngInclude with a template to display each student. I can switch between view by changing bClasseVue, each switch being followed by a $scope.$apply().
<div ng-if="currentCours.classesOfGroup !== undefined"
ng-show="bClassesVue">
<div ng-repeat="group in currentCours.classesOfGroup">
<br>
<h2>Classe : [[group.name]]</h2>
<div class="list-view">
<div class="twelve cell"
ng-repeat="eleve in group.eleves | orderBy:'lastName'"
ng-include="'liste_eleves.html'">
</div>
</div>
</div>
</div>
<div class="list-view" ng-show="!bClassesVue">
<div class="twelve cell"
ng-repeat="eleve in currentCours.eleves.all"
ng-include="'liste_eleves.html'">
</div>
</div>
My problem happens when my list of students change (currentCours here). Instead of refreshing the ngRepeat, both lists concatenate, but only in the unfiltered view.
I tried adding some $scope.$apply in strategic places (and I synchronize my list for example) but it doesn't help.
EDIT : the function used to refresh currentCours in the controller. It's called when a "cours" is selected inside a menu.
$scope.selectCours = function (cours) {
$scope.bClassesVue = false;
$scope.currentCours = cours;
$scope.currentCours.eleves.sync().then(() => {
if ($scope.currentCours.classe.type_groupe === 1) {
let _elevesByGroup = _.groupBy($scope.currentCours.eleves.all, function (oEleve) {
return oEleve.className;
});
$scope.currentCours.classesOfGroup = [];
for(let group in _elevesByGroup) {
$scope.currentCours.classesOfGroup.push({
name: group,
eleves: _elevesByGroup[group]
});
}
$scope.bClassesVue = true;
}
});
utils.safeApply($scope);
};
Well, I found a workaround, but I still don't know why it didn't work, so if someone could write an explanation, I would be very thankful.
My solution was simply to open and close the template each time I switch between views.

How to get the key of a firebaseArray object

I am trying to get the key for a returned firebaseArray record but am having no luck.
I have aservice that runs the following to return a store
getStore: function(uid, id){
var ref = firebase.database().ref('u/'+uid+'/stores/'+id+'/i/');
// to take an action after the data loads, use the $loaded() promise
return $firebaseArray(ref);
}
I use the following to get eeach record by calling the service
for(var i = 0; i < $scope.storesList.length; i++){
var storeInfo = Stores.getStore($rootScope.user['uid'], $scope.storesList[i]['$id']);
storeInfo.$loaded().then(function(data){
$scope.stores.push(data);
console.log($scope.stores);
});
}
In my html I can access various properties within the array
<li ng-repeat="store in stores">
<span class="store-address">{{store.$getRecord('name').$value}}</span>
<span class="store-address">{{store.$getRecord('address1').$value}}</span>
</li>
But I cannot seem to get the id for each store record from within the ng-repeat
To get the id simply call the $id on the item.
<li ng-repeat="store in stores">
<span class="store-address">{{store.$getRecord('name').$value}}</span>
<span class="store-address">{{store.$getRecord('address1').$value}}</span>
<span class="store-address">{{store.$id}}</span>
</li>
See: https://github.com/firebase/angularfire/blob/master/docs/reference.md#firebasearray
Instead of getting yourself complicated, try this simple code!
var ref = new Firebase(url);
ref.once("value", function(list) {
var subData = list.val();
var subDataKey = list.key();
console.log(subDataKey);
This must help you!
I solved this by switch from firebaseArray to firebaseObject which contains an $id parameter

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?

Angularjs - Pagination appear after search filter

I am newbie on AngularJS.
Search result can be displayed in one page but why the next and previous button is showing ?
http://jsfiddle.net/2ZzZB/1473/
<input type="text" id="txtNotessearch" ng-model="search_notes" class="form-control input-sm" placeholder="SEARCH">
...
<ul>
<li ng-repeat="item in data | filter:search_notes | startFrom:currentPage*pageSize | limitTo:pageSize">
{{item}}
</li>
</ul>
Correct me, if I am wrong.
Because NumberOfPages is not filtered.
Instead of using $scope.data.length, you should use the length after the filter.
function MyCtrl($scope, $filter) { //Do not forget to inject $filter
$scope.currentPage = 0;
$scope.pageSize = 10;
$scope.data = [];
$scope.numberOfPages=function(){
var myFilteredData = $filter('filter')($scope.data,$scope.search_notes); //Filter the data
return Math.ceil(myFilteredData.length/$scope.pageSize);
}
for (var i=0; i<45; i++) {
$scope.data.push("Item "+i);
}
}
In addition, I would modify the ng-disable next button to
button "ng-disabled="(currentPage + 1) == numberOfPages()"
And I would add to search_notes onchange currentPage=1.
Here you have the fiddle
http://jsfiddle.net/rLots5zd/
In case, you want to hide the next and previous button when the result can be displayed in one page, please see the fiddle here: http://jsfiddle.net/rLots5zd/3/

AngularJs delete record on nested grouped rows

I'm trying to build a simple page to group record and then add a button to eliminate some records.
The problem is that the record eliminated that has the same name is deleted from the wrong grouped list. And also if a list have no grouped records should disappear, and instead is always there.
Fiddle: http://jsfiddle.net/Tropicalista/qyb6N/15/
// create a deferred object to be resolved later
var teamsDeferred = $q.defer();
// return a promise. The promise says, "I promise that I'll give you your
// data as soon as I have it (which is when I am resolved)".
$scope.teams = teamsDeferred.promise;
// create a list of unique teams
var uniqueTeams = unique($scope.players, 'team');
// resolve the deferred object with the unique teams
// this will trigger an update on the view
teamsDeferred.resolve(uniqueTeams);
// function that takes an array of objects
// and returns an array of unique valued in the object
// array for a given key.
// this really belongs in a service, not the global window scope
function unique(data, key) {
var result = [];
for (var i = 0; i < data.length; i++) {
var value = data[i][key];
if (result.indexOf(value) == -1) {
result.push(value);
}
}
console.log(result)
console.log(Math.ceil(result.length / 10))
$scope.noOfPages = Math.ceil(result.length / 10);
return result;
}
$scope.currentPage = 1;
$scope.pageSize = 5;
$scope.maxSize = 2;
$scope.deleteItem = function(item){
//code to delete here
var index=$scope.players.indexOf(item)
$scope.players.splice(index,1);
};
Here is a sample of something expanding on the tip from SpykeBytes
<div ng-repeat="location in journey.locations">
<div id="location_div_{{ $index }}">
<label class="journey-label">Location name</label>
<input class="journey-input" id="location_{{ $index }}" type="text" ng-model="location.location_name" />
<button ng-show="editable" tabindex="-1" class="journey-button remove" ng-click="removeItem(journey.locations, $index)">
Remove location
</button>
Then in my controller I set up an action that takes deletes the individual item
$scope.removeItem = function(itemArray, index) {
return itemArray.splice(index, 1);
};
To hide the group when nothing is listed, you need to get the filtered list and then use ng-show to drive the display. This is a bit tricky:
<div ng-show="currentList.length>0" ng-repeat="team in teams| startFrom:(currentPage - 1)*pageSize | limitTo:pageSize | filter:searchInput"> <b>{{team}}</b>
<li ng-repeat="player in (currentList = (players | filter: {team: team}))">{{player.name}}
<button class="btn btn-small" type="button" ng-click="deleteItem(player)">Delete</button>
</li>
</div>
However I am not seeing the problem you said about removing from wrong group. Can you let me know how to reproduce it?
Index won't help you here because the {{$index}} that ng-repeat provides is within the groupings. That is, each grouping restarts the $index variable. You are going to need a unique identifier for each record though. Without that there is no way to be sure that the record you want to remove is the right one.
As far as the groupings, you can recreate the model whenever you delete something. This wouldn't work with the sample data in the Fiddle, but it works when you're dealing with a real datasource.
You can instead pass the index of the object if it is within ng-repeat.

Resources