angularjs dynamic add option field with disable previous selected option - angularjs

Hi I am adding Dynamically form fields like this
<div ng-repeat="exam_student in exam_students">
<select
ng-model="exam_student.student_id"
options="students"
ng-options="student.id as student.name for student in students">
</select>
<button type="button" ng-click="removeStudent($index)">-</button>
</div>
<button type="button" ng-click="addStudent()">Add Student</button>
js
$scope.students = [{id: 1, name: 'st1'},
{id: 2, name: 'st2'}];
$scope.exam_students = [{}];
$scope.addStudent = function(){
$scope.exam_students.push({});
}
$scope.removeStudent = function(index){
$scope.exam_students.splice(index,1);
}
Each time a user clicks on Add Student button the form field added but how do i disable the previous selected option in a select element.
Thank you for your any help and suggestions

didn't fully test or optimize it, but this is something you can do.
add track by $index in ng-repeat and add ng-disabled in the select tag with
<div ng-controller='MyController'>
<div ng-repeat="exam_student in exam_students track by $index">
<select
ng-model="exam_student.student_id"
options="students"
ng-options="student.id as student.name for student in students"
ng-disabled="exam_students.length > 1 && exam_students.length > $index + 1">
</select>
<button type="button" ng-click="removeStudent($index)">-</button>
</div>
<button type="button" ng-click="addStudent()">Add Student</button>
</div>
https://jsfiddle.net/4xfzmuub/
exam_students.length > 1 is to prevent the first field from being disabled
===========================================================================
updated answer. Instead of using select with ng-options, I chose to use select with ng-repeat option. This was what I tried and not working.
ng-options="student.id as student.name disable when student.disable for student in students"
The options were able to be disabled. Unfortunately Angular won't let me set the value to ng-model since the option has been disabled. A workaround is to use select with ng-repeat option
html:
<div ng-controller='MyController'>
<div ng-repeat="exam_student in exam_students track by $index">
<select ng-model="exam_student.student_id" ng-change="hasChange()">
<option ng-repeat="student in students" value={{::student.id}} ng-disabled="student.disable">{{::student.name}}</option>
</select>
<button type="button" ng-click="removeStudent($index)">-</button>
</div>
<button type="button" ng-click="addStudent()">Add Student</button>
</div>
js:
var app = angular.module('myApp', []);
app.controller('MyController', ['$scope', MyController]);
function MyController($scope) {
// I suggest adding an empty object so that we can re-select the options
$scope.students = [{},{id: 1, name: 'st1', disable: false},
{id: 2, name: 'st2', disable: false},
{id: 3, name: 'st3', disable: false}];
$scope.exam_students = [{}];
$scope.addStudent = function(){
$scope.exam_students.push({});
}
$scope.removeStudent = function(index){
$scope.exam_students.splice(index,1);
$scope.hasChange();
}
$scope.hasChange = function() {
// using a lookup table, instead of 2 nested loops, for a better performance when the list gets large
var lookupTable = {};
// store the student_id in the lookupTable and set it to true
// worth noting since I am using option tag, student_id will be stored as string instead of number, but it is ok because key in javascript object will be converted to string
$scope.exam_students.forEach(function(exam_student) {
lookupTable[exam_student.student_id] = true;
// or lookupTable[Number(exam_student.student_id)] = true;
});
// loop through the options and if student_id is true/there, set disable accordingly
$scope.students.forEach(function(student) {
if(lookupTable[student.id]) {
student.disable = true;
}else {
student.disable = false;
}
//or student.disable = lookupTable[student.id];
});
}
}
https://jsfiddle.net/apop98jt/

Related

Select All directive in AngularJS

I am using Checklist model directive with my App. I have issue, if -
I click select all button though it write up the array but its not
selecting checkbox. Same issue with Uncheck All though it empty the
model but it doesn't uncheck checkboxes.
If I select 2 or 3 randomly checkbox and click Select All Button it doesn't select All check-boxes.
Though its writing values to pushArray. But issues are checking and unchecking checkboxes.
$scope.items = [{id:1, name:"abc"},{id:2, name:"def"},{id:3, name:"ghi"}];
$scope.pushArray = [];
<table>
<tr ng-repeat="e in items">
<td class="text-right">
{{e.id}}
<input type="checkbox" checklist-change="imChanged()" checklist-model="pushArray" checklist-value="e.id" >
</td>
</tr>
</table>
I think you are pushing the complete list of object which is wrong. You just need to map the list and pass the id to the $scope
Edit: Works fine when you use $scope.pushArray as an object instead of array.
Working Plnkr
HTML
<body ng-controller="selection">
<table>
<tr ng-repeat="e in items">
<td>
<input type="checkbox" checklist-model="pushArray.ids" checklist-value="e.id"> {{e.name}}
</td>
</tr>
</table>
{{pushArray.ids | json}}
<br />
<button ng-click="select_all();">Select All</button>
<button ng-click="unselect_all();">Unselect All</button>
</body>
JS
var app = angular.module('app', ["checklist-model"]);
app.controller('selection', ['$scope', function($scope) {
$scope.items = [{
id: 1,
name: "abc"
}, {
id: 2,
name: "def"
}, {
id: 3,
name: "ghi"
}];
$scope.pushArray = { ids: []}; // Works fine when using it as an object
//$scope.pushArray = [];
$scope.select_all = function() {
$scope.pushArray.ids = $scope.items.map(function(item) { return item.id; });
};
$scope.unselect_all = function() {
$scope.pushArray.ids = [];
};
}]);
Hope it works for you!
I updated the examples on checklist-model and fix this issue. Check them out http://vitalets.github.io/checklist-model/

how get the list of selected items in angular.js

Here I am using angular.js to show a list of people
<div class="recipient" ng-repeat="person in people">
<img src="{{person.img}}" /> person.name
<div class="email">person.email</div>
</div>
$scope.people = [{id:1}, {id:2}, {id:3}, {id:4}];
The looks is like below
What I want to do is I can select multiple items and by click a OK button, I can get a list of selected items. so If I select id 1 and id 2, then I want to get return a list of [{id:1},{id:2}]
How could I implement it in angular.js
Well I guess that if you're looping through a collection of people using a ng-repeat, you could add the ng-click directive on each item to toggle a property of you're object, let's say selected.
Then on the click on your OK button, you can filter all the people that have the selected property set to true.
Here's the code snippet of the implementation :
<div class="recipient" ng-repeat="person in people" ng-click="selectPeople(person)">
<img src="{{person.img}}" /> person.name
<div class="email">person.email</div>
</div>
<button ng-click="result()">OK</button>
function demo($scope) {
$scope.ui = {};
$scope.people = [{
name: 'Janis',
selected: false
}, {
name: 'Danyl',
selected: false
}, {
name: 'tymeJV',
selected: false
}];
$scope.selectPeople = function(people) {
people.selected = !people.selected;
};
$scope.result = function() {
$scope.ui.result = [];
angular.forEach($scope.people, function(value) {
if (value.selected) {
$scope.ui.result.push(value);
}
});
};
}
.recipient {
cursor: pointer;
}
.select {
color:green;
}
.recipient:hover {
background-color:blue;
}
<script src="https://code.angularjs.org/1.2.25/angular.js"></script>
<div ng-app ng-controller="demo">
<div class="recipient" ng-repeat="person in people" ng-click="selectPeople(person)" ng-class="{ select: person.selected }">
<div class="name">{{ person.name }}</div>
</div>
<button ng-click="result()">OK</button>
Result :
<ul>
<li ng-repeat="item in ui.result">{{ item.name }}</li>
</ul>
</div>
If you only want to show checked or unchecked you could just apply a filter, but you would need to toggle the filter value from undefined to true if you didn't wan't to get stuck not being able to show all again.
HTML:
<button ng-click="filterChecked()">Filter checked: {{ checked }}</button>
<div class="recipient" ng-repeat="person in people | filter:checked">
<input type='checkbox' ng-model="person.isChecked" />
<img ng-src="{{person.img}}" />{{ person.name }}
<div class="email">{{ person.email }}</div>
</div>
Controller:
// Apply a filter that shows either checked or all
$scope.filterChecked = function () {
// if set to true or false it will show checked or not checked
// you would need a reset filter button or something to get all again
$scope.checked = ($scope.checked) ? undefined : true;
}
If you want to get all that have been checked and submit as form data you could simply loop through the array:
Controller:
// Get a list of who is checked or not
$scope.getChecked = function () {
var peopleChkd = [];
for (var i = 0, l = $scope.people.length; i < l; i++) {
if ($scope.people[i].isChecked) {
peopleChkd.push(angular.copy($scope.people[i]));
// Remove the 'isChecked' so we don't have any DB conflicts
delete peopleChkd[i].isChecked;
}
}
// Do whatever with those checked
// while leaving the initial array alone
console.log('peopleChkd', peopleChkd);
};
Check out my fiddle here
Notice that person.isChecked is only added in the HTML.

AngularJS select value from options and add to array

I am new with AngularJS. I want to add values into array and display those in table after clicking on Save button.
One is select Menu and other is TextBox. Presently, I am able to add text value but not able to get selected value.
Here is what I have:
clusterController.js
apsApp.controller('clusterController', function ($scope) {
var uid = 4;
$scope.clusters=[
{id:0, 'environment':'DEV', 'cluster':'cluster1'},
{id:1, 'environment':'PROD', 'cluster':'cluster2'},
{id:2, 'environment':'QA', 'cluster':'cluster3'},
{id:3, 'environment':'Linux_Dev', 'cluster':'cluster4'}
];
//add new cluster
$scope.saveNewClust = function() {
if($scope.clust.id == null) {
//if this is new contact, add it in contacts array
$scope.clust.id = uid++;
$scope.clusters.push($scope.clust);
}
else {
//for existing contact, find this contact using id
//and update it.
for(i in $scope.clusters) {
if($scope.clusters[i].id == $scope.clust.id) {
$scope.clusters[i] = $scope.clust;
}
}
};
//clear the add contact form
$scope.clust = {};
};
//delete cluster
$scope.remove = function(id) {
//search contact with given id and delete it
for(i in $scope.clusters) {
if($scope.clusters[i].id == id) {
confirm("This Cluster will get deleted permanently");
$scope.clusters.splice(i,1);
$scope.clust = {};
}
}
};
$scope.edit = function(id) {
//search contact with given id and update it
for(i in $scope.clusters) {
if($scope.clusters[i].id == id) {
//we use angular.copy() method to create
//copy of original object
$scope.clust = angular.copy($scope.clusters[i]);
}
}
};
});
cluster.html
<div class="maincontent">
<div class="article">
<form>
<section>
<!-- Environment -->
<div class="col-md-6">
<label>Environment:</label>
<select ng-model="selectedEnvi" class="form-control" ng-options="clust.environment for clust in clusters">
<option value='' disabled selected style='display:none;'>
Select Environment
</option>
</select>
</div>
<!-- cluster Name -->
<div class="col-md-6">
<label>Cluster Name:</label>
<input type="text" class="form-control" name="clusterName" placeholder="Cluster" ng-model="clust.cluster" required>
<br/>
<input type="hidden" ng-model="clust.id" />
</div>
</section>
<!-- submit button -->
<section class="col-md-12">
<button type="button" class="btn btn-default pull-right" ng-click="saveNewClust()">Save Cluster</button>
</section>
</form>
</div>
<!-- table -->
<div class="article">
<table class="table table-bordered table-striped">
<tr>
<th colspan="3">
<div class="pull-left">Cluster Info</div>
</th>
</tr>
<tr>
<th>#</th>
<th>Environment</th>
<th>Cluster</th>
</tr>
<tr ng-repeat="clust in clusters">
<td>{{}}</td>
<td>{{clust.environment}}</td>
<td>{{clust.cluster}}</td>
</tr>
</table>
</div>
</div>
First of all, make an own array for the possible selections of the environment selections. Right now you get the possible values from an existing list of clusters (you can leave it like this of course, but I find it confusing!). Let's just go with the following:
$scope.environments = [
{name: 'DEV',},
{name: 'PROD',},
{name: 'QA',},
{name: 'Linux_Dev'}
];
Furthermore, you need to preselect an environment in ngModel for the select values. We need to do this, because after the page is loaded, the select box maybe shows "DEV", but it doesn't set the ngModel to "DEV". It only updates the ngModel after manually selecting a value.
Set it like this:
$scope.selectedEnvironment = $scope.environments[0];
This sets the model "selectedEnvironment" to {name: "Dev"}.
The selection box:
<select ng-model="selectedEnvironment" class="form-control" ng-options="environment.name for environment in environments">
<option disabled value="">-- choose environment --</option>
</select>
I set the model to "selectedEnvironment", so the preselection from the controller will work. I also changed hg-options to use the JSON which contains the environment names.
The last thing to do is a minor change on the "saveNewClust" function:
if ($scope.clust.id == null) {
//if this is new contact, add it in contacts array
$scope.clust.id = uid++;
$scope.clust.environment = $scope.selectedEnvironment.name;
$scope.clusters.push($scope.clust);
}
What happens: We just give the name of the environment to $scope.clust.environment.
I made a fiddle containing the working demo:
http://jsfiddle.net/hs6Rz/9/

update fields in ngRepeat based on another field in same index

I want to be able to populate a text input field inside an ng-repeat loop with the value of another field inside that same loops index when I click a button.
JSFiddle of what I have so far: http://jsfiddle.net/3FKMx/
When the Copy Names button is clicked I want each text box to be populated with the same value that's in the array. Currently it populates them all with the value of the last item in the array.
Controller:
var app = angular.module('myApp', []);
function someController($scope) {
$scope.names = ["name1","name2","name3"];
$scope.copyNames = function() {
angular.forEach($scope.names,
function (value){
$scope.newName = value;
}
);
};
}
Template:
<div ng-controller="someController">
<button class="btn btn-primary" ng-click="copyNames()">Copy Names</button>
<table>
<tr ng-repeat="name in names">
<td>{{name}}</td>
// I want to populate this input with {{ name }} when I click the button above.
<td><input type="text" ng-model="newName"/></td>
</tr>
</table>
</div>
Solution 1
With an updated data structure it's a bit nicer for looping through.
Solution 2
Create a new array to store the values. Set them by key and look them up by key in your curly braces.
html
<div ng-controller="someController">
<button class="btn btn-primary" ng-click="copyNames()">Copy Names</button>
<table>
<tr ng-repeat="name in names">
<td>{{name}}</td>
<td><input type="text" ng-model="models[name]"/></td>
</tr>
</table>
</div>
JavaScript
var app = angular.module('myApp', []);
function someController($scope) {
$scope.names = ["name1","name2","name3"];
$scope.models = {};
$scope.copyNames = function() {
angular.forEach($scope.names,
function (value, key) {
$scope.models[value] = value;
}
);
};
}
DEMO (updated your fiddle) is what you are looking for?
Tried using an object to hold the label and model:
$scope.names = [{label: "name1", model: ''},
{label: "name2", model: ''},
{label: "name3", model: ''}];
//Also using jQuery.each to break from the loop
//once we know which value to copy
$scope.copyNames = function() {
$.each($scope.names,
function (i, value){
if(value.model) {
angular.forEach($scope.names, function(name){
name.model = value.model;
});
//Break the loop if done copying
return false;
}
}
);
};
Note: jQuery is used as an external library which will be available in angular as is.

AngularJs Select Not Updating When Model Updated

I'm trying to programmatically update the selected item from my controller and it's not working. When I click the submit button, all it does is clear out the select. What I expect is that the second option (Perth) gets selected.
Look at this plunker for more info. http://jsfiddle.net/ky5F4/
Thanks
<div ng-controller="MyController" ng-app>
<div>Number of datasets= {{datasets.length}}</div>
<div>
<select class="dataset" size="1" ng-model="selectedDataset">
<option ng:repeat="dataset in datasets" value="{{dataset.name}}">
<h3>{{dataset.name}}</h3>
</option>
</div>
<input type="button" value="submit" ng-click="Select()"></input>
</div>
function MyController($scope) {
$scope.datasets = [{
id: 'id-1',
name: 'Brisbane'
}, {
id: 'id-2',
name: 'Perth'
}, {
id: 'id-3',
name: 'Melbourne'
}];
$scope.selectedDataset = 'id-1';
$scope.Select = function () {
alert('testing');
$scope.selectedDataset = 'id-2';
}
}
Use ng-options instead of ng-repeat.
<select class="dataset" size="1" ng-model="selectedDataset"
ng-options="dataset.id as dataset.name for dataset in datasets">
Working fiddle
You can see the docs here

Resources