Angularjs select display value if not in array - angularjs

I would like to create a select for add and remove value in my array. But the value must be unique.
This is my code but dosen't work correctly because I don't know how I can to hide or show the value in the select
<div ng-app="myApp">
<div ng-controller="myController">
<p>Select something</p>
<select ng-model="selectedBucket"
ng-options="row as row.display for row in bucketEnum | filter:bootstrapValues">
</select>
<button ng-click="add(selectedBucket.value)">
add
</button>
<br>
{{initialSet}}
<br>
{{bucketEnum}}
</div>
</div>
And controller and filters :
var app = angular.module('myApp', []);
app.controller('myController', function ($scope, $filter) {
$scope.initialSet = [1, 2, 4, 7];
$scope.bucketEnum = [
{ display: '0', value: 0, bool:true },
{ display: '1', value: 1, bool:true},
{ display: '2', value: 2, bool:true },
{ display: '3', value: 3, bool:true },
{ display: '4', value: 4, bool:true },
{ display: '5', value: 5, bool:true },
{ display: '6', value: 6, bool:true },
{ display: '7', value: 7, bool:true }
];
$scope.add = function(value){
$scope.initialSet.push(value);
$scope.selectedBucket = $filter('bootstrapValues')($scope.initialSet, $scope.bucketEnum);
}
});
app.filter('bootstrapValues', function(){
return function(initial, baseBucket){
var result = [];
for(var i = 0; i < initial.length; i++){
var flag = false;
for(var j=1; j<baseBucket.length; j++){ //from 1 or 0.. you call
if(initial[i] === baseBucket[j].value){
flag = true;
baseBucket[j].bool = false;
break; // if there are repeated elements
}
}
}
return result;
};
});

If you want to disable the added value in current select, then You can achieve this by disable when syntax of angular 1.4+ version
See this fiddle of your code.(for disable)
and, If you want to delete the added value in current select then See this fiddle (for delete)

Related

show checkbox elements of an array of checkboxes

I have got a set of radiobuttons and an array of checkboxes. When i click radiobutton1 it should load first checkbox element from the array and when i click radiobutton2 it should load remaining 3 checkbox elements from the array.But it shows all 4 checkboxes in both the cases. I tried like this.
In HTML
<form>
<label class="radio-inline" >
<input value="1" type="radio" ng-model="radioption" >RB1</label>
<label class="radio-inline">
<input value="2" type="radio" ng-model="radioption" >RB2</label>
<div class="">
<label ng-repeat="channel in channels | filter:myFilter" >
<input type="checkbox" name="selectedChannels[]" value="{{channel.value}}"
ng-model="channel.selected" >{{channel.name}}
</label></div>
</form>
In Controller
App.controller('ReportController', ['$scope', 'Report', function($scope, Report){
var self = this;
$scope.channels = [{ name: 'A', selected: false, value: '1',visible:false },
{ name: 'B', selected: false, value: '2' ,visible:false},
{ name: 'C', selected: false, value: '3' ,visible:false},
{ name: 'D', selected: false, value: '4' ,visible:false}
];
$scope.selection = [];
$scope.selectedChannels = function selectedChannels() {
return Report($scope.channels, { selected: true } );
};
$scope.$watch('channels|filter:{selected:true}', function (new) {
$scope.selection = new.map(function (channel) {
return channel.value;
});
}, true);
$scope.myFilter = function(){
if ($scope.radioption == '1'){
return $scope.channels[0].visible = true;
}
else if ($scope.radioption == '2'){
return [$scope.channels[1],{ visible: true },
$scope.channels[2],{ visible: true },
$scope.channels[3],{ visible: true }];
}
});
}]);
I think you should approach this problem differently but if you want to use a filter try this
$scope.myFilter = function (channel) {
if ($scope.radioption == 1) {
if (channel.name == 'A') {
return true;
}
else {
return false;
}
}
else if ($scope.radioption == 2) {
if (channel.name == 'A') {
return false;
}
else {
return true;
}
}
else {
return false;
}
}
or you can add radioption column to channels array
$scope.channels = [{ name: 'A', selected: false, value: '1', radioption: 1 },
{ name: 'B', selected: false, value: '2', radioption: 2 },
{ name: 'C', selected: false, value: '3', radioption: 2 },
{ name: 'D', selected: false, value: '4', radioption: 2 }
];
and use ng-show
<input type="checkbox" ng-show="channel.radioption == radioption" name="selectedChannels[]" value="{{channel.value}}"
ng-model="channel.selected">{{channel.name}}
You need to register your filter with angularJS. e.g.
app.filter('myFilter', function() {
return function(input) {
var output;
// Do filter work here
return output;
}
Then you can use your filter in the HTML.
Also - filter should get input and return a filtered output. I think it make less sense to return a strict output regardless of the input given to it.
Take a look here, for example:
https://scotch.io/tutorials/building-custom-angularjs-filters

NaN showing even with number (angularjs)

In the controller:
$scope.startCount = 0;
$scope.vs = function (number) {
$scope.startCount = number;
}
$scope.startTimeout = function () {
$scope.startCount = $scope.startCount + 1;
mytimeout = $timeout($scope.startTimeout, 1000);
}
$scope.startTimeout();
$scope.stopTimeout = function () {
$timeout.cancel(mytimeout);
alert("Timer Stopped");
}
$scope.meals = [
{ title: 'Abs', url:"#/app/mworkouts",id: 100, img: "img/female.jpg", vid:"vid/1.mp4",},
{ title: 'Arms', url:"#/app/browse",id: 2 , img: "img/male.jpg", vid:"vid/2.mp4"},
{ title: 'Biceps', url:"#/app/search",id: 3, img: "img/Spotify_2.jpg", vid:"vid/1.mp4" },
{ title: 'Legs', url:"#/app/search",id: 4, img: "img/Spotify_4.jpg", vid:"vid/2.mp4" },
{ title: 'Core', url:"#/app/mworkouts",id: 5, img: "img/female.jpg", vid:"vid/1.mp4" },
{ title: 'Back', url:"#/app/mworkouts",id: 6, img: "img/male.jpg", vid:"vid/2.mp4" }
];
In the html:
<div ng-repeat="m in meals">
<button ng-click='vs({{m.id}})'>Setter</button>
</div>
So how it is supposed to work is pass in a number from the array and then count up using $timeout. It works perfectly fine if I enter in a number manually but I want the number to come from the array. Also, {{m.id}} is definelty a number because I have tested it {{m.id-60}} and it works. I am have no idea what is wrong.
Sorry about the weird names...it's just an example :)
Just get rid of the {{}}
ng-click='vs(m.id)'
It's seems to work for me here! I added couple of log for you to make sure
<div ng-repeat="m in meals">
<button ng-click='vs(m.id)'>Setter</button>
</div>
http://plnkr.co/edit/tpl:rfqcl9AHEoJZEEJxyNn2?p=preview

angularjs custom filter vs selection lists

I have 6 select lists as the number of options i have and each has 6 options , when i select one options the rest of the section list must not contain the selected anymore
html
<div ng-repeat="filter in filters">
<select ng-model="selected" ng-options="item as item.type for item in filters|filterFnt:selected" ng-click="addProperty(selected)"></select>
js
$scope.selectionList = [] ;
$scope.selected = $scope.filters[0];
$scope.addProperty = function (obj) {
var index = $scope.selectionList.indexOf(obj);
if( index == -1) {
$scope.selectionList.push(obj);
}
};
$scope.filters = [
{
type : 'select one',
inputType : '111',
},
{
type : 'A',
inputType : '111',
},
{
type: 'B',
Xtype : '222'
},
{
type: 'C',
Xtype: '444' ,
},
{
type: 'D',
Xtype : '555'
},
{
type: 'E',
Xtype : '6666'
},
{
type: 'F',
inputType : '777'
}
];
app.filter('filterFnt', function() {
return function(input,x) {
angular.forEach($scope.selectionList, function(item) {
var index = input.indexOf(item);
if( index != -1 && item != x) {
input.splice(index, 1);
}
});
return input
};
});
issue
when i select an option from select list i want to keep that option in the list , what is happening it is being removed from the current one as well
Thank you
Your problem in splice function inside filter: it function change source array, so on every filter changed data for all selects.
Instead splice you can use simple filter function.
Your filter can be like
app.filter('filterFnt', function() {
return function(input, selectionList, selectionObj, filterType) {
//get elements that selected in current select, or not already selected
return input.filter(function(el) {
return selectionObj[filterType] === el || (selectionList.indexOf(el) == -1);
});
};
});
I add selectionObj, this object contain selected item for current select.
Before adding element in selectionList you need remove already added item from current select like
function removeFromSelected(currType){
var o = $scope.selectionObj[currType],
index = $scope.selectionList.indexOf(o);
if (index != -1)
$scope.selectionList.splice(index, 1);
}
var app = angular.module('app', []);
app.controller('ctrl', function($scope) {
function removeFromSelected(currType){
var o = $scope.selectionObj[currType],
index = $scope.selectionList.indexOf(o);
if (index != -1)
$scope.selectionList.splice(index, 1);
}
$scope.addProperty = function(obj, currType) {
removeFromSelected(currType);
if (!obj) {
delete $scope.selectionObj[currType];
} else {
var index = $scope.selectionList.indexOf(obj);
$scope.selectionList.push(obj);
$scope.selectionObj[currType] = obj;
}
};
$scope.filters = [{
type: 'A',
inputType: '111',
}, {
type: 'B',
Xtype: '222'
}, {
type: 'C',
Xtype: '444',
}, {
type: 'D',
Xtype: '555'
}, {
type: 'E',
Xtype: '6666'
}, {
type: 'F',
inputType: '777'
}];
$scope.selectionList = [];
$scope.selectionObj = {};
});
app.filter('filterFnt', function() {
return function(input, selectionList, selectionObj, filterType) {
return input.filter(function(el) {
return selectionObj[filterType] === el || (selectionList.indexOf(el) == -1);
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div ng-repeat="filter in filters">
<select ng-model="selected" ng-options="item as item.type for item in filters|filterFnt:selectionList:selectionObj:filter.type" ng-change="addProperty(selected,filter.type)">
<option value="">select one</option>
</select>
</div>
selectionList - {{selectionList}}
</div>

AngularJS Select Not Binding To Ng-Model

My angular select isn't binding. I can tell the value is correct, but the select isn't updated. Why is not binding if the value is there?
<div ng-controller="MyController" ng-app>
<select class="form-control" ng-model="colorId"ng-options="color.id as color.name for color in colorList">
<option value="">--Select a Color--</option>
</select>
<input type="button" value="submit" ng-click="Select()"></input>
function MyController($scope) {
$scope.colorList = [{
id: '1',
name: 'red'
}, {
id: '2',
name: 'blue'
}, {
id: '3',
name: 'green'
}];
var colorId = 3;
$scope.colorId = colorId;
alert($scope.colorId);
$scope.Select = function () {
var colorId = 2;
$scope.colorId = colorId;
}
}
Here is a fiddle:
http://jsfiddle.net/ky5F4/23/
you need to change the id to a string when doing Select
$scope.Select = function () {
console.log('select fired');
var colorId = 1;
$scope.mySelection.colorId = colorId + "";
}
http://jsfiddle.net/bxkwfo0s/2/
next you should use a property of an object rather than just a scope variable, this will ensure proper model binding
ng-model="mySelection.colorId"
where the object could be something simple
$scope.mySelection = {colorId : colorId };
There are two errors with your code:
You are using colorList as your model in ng-options, but you are calling it datasets in your controller.
You use strings for the id, but set the $scope.colorId to a number.
Here is an updated fiddle changing ids to numbers and changing $scope.datasets to $scope.colorList
function MyController($scope) {
$scope.colorList = [{
id: 1,
name: 'red'
}, {
id: 2,
name: 'blue'
}, {
id: 3,
name: 'green'
}];
var colorId = 3;
$scope.colorId = colorId;
alert($scope.colorId);
$scope.Select = function () {
var colorId = 2;
$scope.colorId = colorId;
}
}
Consider making your ng-model be an object, specifically one of the objects that are already in your $scope.colorList. If you do that you should be able to avoid the post-processing you're doing in the click handler.
So your select will look like this:
<select class="form-control" ng-model="selectedColor"
ng-options="color.name for color in colorList"></select>
One gotcha is that if you have an object in your controller that looks JUST LIKE your red object, like$scope.selectedColorObj = { id : '1', name:'red' } and set the select's ng-model to that option, it won't work. Angular will see that you're setting to the ng-model to an object that's not actually in your data source and add an extra option with value="?", so I use $filter in this case to grab the matching member of the array:
$scope.colorId = '3';
$scope.selectedColor = $filter('filter')( $scope.colorList,{ id: $scope.colorId})[0];
See http://jsfiddle.net/ky5F4/92/

select box : display text 'error' if value not exist in array

I have a key value pair defined as below, which is being used for select using ng-options
$scope.BucketEnum = [
{ display: 'Error', value: 0 },
{ display: '1', value: 1 },
{ display: '2', value: 2 },
{ display: '3', value: 3 },
{ display: '4', value: 4 },
{ display: '5', value: 5 },
{ display: 'Flows', value: 125 },
{ display: 'Recovery', value: 151 }
];
I am using this key value pair to display select box in ng-options
<select ng-model="selectedBucket" ng-options="row.value as rows.display for row in BucketEnum" multiple="multiple" ></select>
now if I set ng-model i.e. $scope.selectedBucket = 10, I want to display the text Error. Is it possible to show value Error for all the values which are not there in $scope.BucketEnum array.
NOTE
I am looking at a more generic way to do this e.g a filter for doing this
SCENARIO
There is certain historical data in database, which has some garbage and some good data.
For each garbage value, i need to show the current garbage value as well as the valid values to select from, so for the end users to fix it.
Would this fit your needs ?
jsfiddle
app.filter('bootstrapValues', function(){
return function(initial, baseBucket){
var result = [];
for(var i=0; i<initial.length; i++){
var flag = false;
for(var j=1; j<baseBucket.length; j++){ //from 1 or 0.. you call
if(initial[i] === baseBucket[j].value){
flag = true;
result.push(baseBucket[j]);
break; // if there are repeated elements
}
}
if(!flag)
result.push(baseBucket[0])
}
return result;
};
});
Using it to start the selectedBucket, in your controller:
// setting initials
$scope.selectedBucket = $filter('bootstrapValues')(initialSet, $scope.bucketEnum);
Does it help?
Edit: Here is other jsfiddle with little modifications, if the value is not in the bucket it add the element to the list with Error display and as a selected value.
Using ng-options generates multiple HTML <select> elements for each item in your BucketEnum array and 'returns' the selected value in your ng-model variable: selectedBucket. I think the only way to display the options without an additional blank entry is to ensure the value of selectedBucket is a valid entry in BucketEnum.
Your question states:
if I set ng-model i.e. $scope.selectedBucket = 10, I want to display
the text Error.
I assume you want to display the value: {{BucketEnum[selectedBucket].display}}
So... starting with $scope.selectedBucket = 10, we want some generic way of implementing a select using ng-options which will reset this value to a default.
You could do this by implementing an attribute directive, allowing you to write:
<select ng-model="selectedBucket" select-default="BucketEnum"
ng-options="row.value as row.display for row in BucketEnum"
multiple="multiple">
An example of this approach is shown below. Note that this assumes the default value is zero and does not handle multiple selections (you'd have to iterate over the selections when comparing to each item in BucketEnum and decide what to do if there is a mix of valid and invalid selections).
app.directive("selectDefault",function(){
return{
restrict: 'A',
scope: false,
link:function(scope,element,attrs){
var arr= scope[attrs.selectDefault]; // array from attribute
scope.$watch(attrs.ngModel,function(){
var i, ok=false;
var sel= scope[attrs.ngModel]; // ng-model variable
for( i=0; i<arr.length; i++){ // variable in array ?
if( arr[i].value == sel ) // nasty '==' only for demo
ok= true;
}
if( ! ok )
scope[attrs.ngModel]=0; // set selectedBucket to 0
});
}
};
});
I've run up a jsfiddle of this here
The downside of this is that I've used a $watch on the ng-model which causes side-effects, i.e. any assignment of the named variable will trigger the $watch function.
If this is the sort of solution you were looking for, you could expand the directive in all sorts of ways, for example:
<select ng-model="selectResult"
select-default="99" array="BucketEnum" initial="selectedBucket"
ng-options="row.value as row.display for row in BucketEnum"
multiple="multiple">
...the idea being that the select-default directive would read the default value ("99" here), the array and an initial value then set selectResult accordingly
You would need to code for this explicitly. Scan the choices you want to set against the choices that are present. If you don't find it, select the Error value too.
Note also that you need to pass an array for selectedBucket and it needs to include the actual option objects not just the values inside them.
<div ng-app="myApp">
<div ng-controller="myController">
<p>Select something</p>
<select ng-model="selectedBucket"
ng-options="row as row.display for row in bucketEnum" multiple="multiple">
</select>
</div>
</div>
.
var app = angular.module('myApp', []);
app.controller('myController', function ($scope) {
var initialSet = [1, 5, 10];
$scope.bucketEnum = [
{ display: 'Error', value: 0 },
{ display: '1', value: 1 },
{ display: '2', value: 2 },
{ display: '3', value: 3 },
{ display: '4', value: 4 },
{ display: '5', value: 5 },
{ display: 'Flows', value: 125 },
{ display: 'Recovery', value: 151 }
];
var selected = [];
var error = $scope.bucketEnum[0];
angular.forEach(initialSet, function(item) {
var found;
angular.forEach($scope.bucketEnum, function (e) {
if (+item == +e.value) {
console.log('Found ', e);
found = item;
selected.push(e);
}
});
if (typeof found === 'undefined') {
selected.push(error);
}
$scope.selectedBucket = selected;
console.log(selected);
});
});

Resources