I have three checkboxes:-
<label>Type:</label>
<label>one</label>
<input type="checkbox" name="type" ng-model="a.Type[0]"/>
<label>two</label>
<input type="checkbox" name="type" ng-model="a.Type[1]"/>
<label>three</label>
<input type="checkbox" name="type" ng-model="a.Type[2]"/>
These checkboxes are stored in the backend as an array of string.
My value is displaying in:-
<li class="list-group-item"><strong>Type</strong>: <span ng-repeat="values in myArray">{{values}}</span></li>
My directive code is:-
(function () {
'use strict';
angular.module('myApp.components')
.directive('abc', abc);
abc.$inject = ['$http', '$timeout', 'ApiServices'];
function abc($http, $timeout, ApiServices) {
return {
restrict: 'EA',
scope: {
},
link: function (scope, el, attrs) {
scope.a = {};
$('#abc').on('hide.bs.modal', function () {
scope.active = false;
});
$('#abc').on('shown.bs.modal', function () {
scope.active = true;
scope.myArray = [];
scope.iterate = function () {
for (var key in scope.a.Type) {
if (scope.a.Type.hasOwnProperty(key)) {
scope.myArray.push(scope.a.Type[key]);
}
}
};
scope.iterate();
},
templateUrl: ''
};
}
})();
Here what I am trying to do is- I want to iterate through 'Type' checkboxes and pushed the values in 'myArray', and then display only the values.
Probably, my example below is somewhat similar to what you are looking for:
HTML:
<span>Select Type:</span>
<div ng-repeat="type in myArray">
<input type="checkbox" ng-model="type.value" /> {{type.type}}
</div>
<span>Selected Types:</span>
<div ng-repeat="type in myArray">
<span ng-show="type.value"> {{type.type}}</span>
</div>
JS:
$scope.a = {};
$scope.a.Type = ["One","Two","Three"]; // your string array
$scope.myArray = [];
$scope.a.Type.forEach(function(item){
$scope.myArray.push({type: item, value: false }); // create new array to make it selectable via checkbox
});
I guess, you no more need your directive now. The iteration and filtering is done in HTML itself.
I hope this helps.
Related
I have a service, say this one that returns
{"001":"Communication","002":"Developement","003":"Environment","004":"Equipment"}
I need to put this all in checkboxes, users enable-disable them and finally I recuperate the checked values as CSV keys.
Say user checked the "Development" and "Equipment", so I need to obtain in the "002,004" value.
Here is my codepen with some values already checked (002-Developement and 003-Environment):
angular.module('tagsApp', [])
.controller('tagsController', ['$scope', '$http', function ($scope, $http) {
// an initial value is present in the #Tags hidden element
$scope.tags = $('#Tags').val();
var tags = $scope.tags.split(",");
// I need an obj['key']='key' array
$scope.myTagsArray = {};
tags.forEach(function (tag) { $scope.myTagsArray[tag] = tag; });
// get all possible values
$http.get("http://www.mocky.io/v2/597866a7130000d704c0fed3")
.then(function (response) {
$scope.allTags = response.data;
});
$scope.change = function (myTagsArray) {
console.log("myTagsArray: '" + Object.values($scope.myTagsArray).join(",") + "' !");
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="tagsApp">
<label>Tags</label>
<div ng-controller="tagsController">
<input type="hidden" id="Tags" value="002,003"/>
<div ng-cloak ng-repeat="(key, value) in allTags">
<label for="tag_{{key}}">
<input type="checkbox"
id="tag_{{key}}"
ng-model="tagsArray['{{key}}']"
ng-true-value="'{{key}}'"
ng-false-value=""
ng-change="change(tagsArray)" />
{{value}}
</label>
</div>
</div>
</div>
However all that code does not really work. Where is the problem?
You can try the below code if you want the corresponding keys to be saved on checking
angular.module("tagsApp", []).controller("tagsController", [
"$scope",
"$http",
function($scope, $http) {
// get all possible values
$scope.allTags = {
"001": "Communication",
"002": "Developement",
"003": "Environment",
"004": "Equipment"
};
$scope.hidval="002,003";
$scope.checked = [];
$scope.tags = [];
$scope.keys = [];
$scope.tags = $scope.hidval.split(",");
$scope.tags.forEach(function(tag) {
$scope.checked[tag] = true;
$scope.keys.push(tag);
});
$scope.change = function(mykey) {
var ind = $scope.keys.indexOf(mykey);
if ($scope.checked[mykey]) {
$scope.checked[mykey] = false;
$scope.keys.splice(ind, 1);
} else {
$scope.checked[mykey] = true;
$scope.keys.push(mykey);
}
var result=$scope.keys.join();
console.log(result);
$scope.hidval=result;
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="tagsApp">
<label>Tags</label>
<div ng-controller="tagsController">
<input type="hidden" id="Tags" ng-model="hidval"/>{{hidval}}
<div ng-cloak ng-repeat="(key, value) in allTags">
<label for="tag_{{key}}">
<input type="checkbox"
id="tag_{{key}}"
ng-checked="checked[key]"
ng-click="change(key)"/>
{{value}}
</label>
</div>
</div>
</div>
Based on the Vivz answer (thanks a lot for the effort), here is the working solution
angular.module("tagsApp", []).controller("tagsController", [
"$scope",
function($scope) {
// get all possible values
$scope.allTags = {
"001": "Communication",
"002": "Developement",
"003": "Environment",
"004": "Equipment"
};
$scope.selectedTags = $("#Tags").val().split(",");
$scope.tagsArray = {};
// init all with "false"
Object.keys($scope.allTags).forEach(function(tag) { $scope.tagsArray[tag] = ""; });
// check pre-selected from hidden #Tags
$scope.selectedTags.forEach(function(tag) { $scope.tagsArray[tag] = tag; });
$scope.change = function(mykey) {
var result = Object.values($scope.tagsArray)
.filter(function(o){return o;})
.join(); // remove the empty values in array
$("#Tags").val(result); // update the hidden #Tags
console.log(result);
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="tagsApp">
<label>Tags</label>
<div ng-controller="tagsController">
<input type="hidden" id="Tags" value="002,003"/>
<div ng-cloak ng-repeat="(key, value) in allTags">
<label for="tag_{{key}}">
<input type="checkbox"
id="tag_{{key}}"
ng-model="tagsArray[key]"
ng-true-value="{{key}}"
ng-false-value=""
ng-change="change(key)" />
{{value}}
</label>
</div>
</div>
</div>
How can I have one checkbox checked by default when the page loads between two toggling check boxes. my code:
jsfiddle: http://jsfiddle.net/Lvc0u55v/456/
function MyCtrl($scope) {
$scope.changeAxis1 = function() {
if ($scope.thirtyDay) {
$scope.wholeTimeline = false;
}
};
$scope.changeAxis2 = function() {
if($scope.wholeTimeline) {
$scope.thirtyDay = false;
}
};
};
view
<label class='checkboxes' id='checkbox_1'>
<input type="checkbox" ng-model="thirtyDay" ng-change="changeAxis1()">
Two
</label>
<label class='checkboxes' id='checkbox_2'>
<input type="checkbox" ng-model="wholeTimeline" ng-change="changeAxis2()">
One
</label>
Initialize one of the values to true in your controller:
function MyCtrl($scope) {
$scope.changeAxis1 = function() {
if ($scope.thirtyDay) {
$scope.wholeTimeline = false;
}
};
$scope.changeAxis2 = function() {
if($scope.wholeTimeline) {
$scope.thirtyDay = false;
}
};
$scope.thirtyDay = true;
};
You also need to have ng-app and ng-controller in your view in order for Angular to do anything:
<div class="checkbox" ng-app="" ng-controller="MyCtrl">
http://jsfiddle.net/Lvc0u55v/457/
You can use ng-checked="expression"
<input type="checkbox" ng-checked="expression" ng-model="thirtyDay" ng-change="changeAxis1()">
Two
and put some logic for expression how you want the checkbox to be checked
I cannot figure out how can I count form fields which are valid:
For template i'm using common code:
<p class="input-group" ng-repeat="pomiar in pomiary track by $index">
<input type="number" class="form-control" ng-model="pomiar" is-float/>
<span class="input-group-btn">
<input class="btn btn-danger" ng-click="usunPomiar($index)"
type="button" value="X">
</span>
</p>
Validation is done via directive :
.directive('isFloat', function ($filter) {
var FLOAT_REGEXP_3 = /^\$?\d+(\.\d*)?$/; //Numbers like: 1123.56
var FLOAT_REGEXP_4 = /^\$?\d+(\,\d*)?$/; //Numbers like: 1123,56
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function (viewValue) {
if (FLOAT_REGEXP_3.test(viewValue)) {
ctrl.$setValidity('float', true);
return parseFloat(viewValue);
} else if (FLOAT_REGEXP_4.test(viewValue)) {
ctrl.$setValidity('float', true);
return parseFloat(viewValue.replace(',', '.'));
}else {
ctrl.$setValidity('float', false);
return undefined;
}
});
ctrl.$formatters.unshift(
function (modelValue) {
return $filter('number')(parseFloat(modelValue) , 2);
}
);
}
};
});
I would like to display nuber of fields(inputs) in the template or store it in variable.
No problem if input isn't array and name attribute 'pomiar' is set:
{{myForm.pomiar.$valid}}
Do I have to write function in controller to validate it once again, or is there simpler way?
Hi everyone I'm use angularjs not so long time ago and now I have one issue related with this framework that i can't to solve. So the problem in next: I have few input fields that generate via ng-repeat:
<div class="form-group" ng-repeat="(i, name) in name_list track by $index">
<div class="row">
<div class="col-xs-12">
<input class="form-control" type="text" ng-model="data.name_list[i]" add-input/>
</div>
</div>
Where name_list some array with data. As result I have generated input fields. Next that i wanted to do it's adding new input field if all previously fields was $dirty for this thing i wrote next angular code:
userApp.directive('addInput', ['$compile', '$sce', function ($compile, $sce) {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ngModel) {
scope.inputCounter = scope.name_list.length;
scope.$watch(
function(){
return ngModel.$dirty
},
function(dirty_val){
if (dirty_val){
scope.name_list.push(ngModel.$modelValue);
}
}
);
}
}}]);
but of course this code works wrong (it add new field if at last one field is $dirty) I know why it works wrong but I do not know how to track all ng-models separate, I don't know how to get access to some model like ngModel[1],so I hope somebody will help me in this, thank's
You could add a parent directive which will collect the dirty elements, and will add new element once it detects all of the other elements are dirty:
Check this plunker.
HTML:
<div collect-input>
<div class="form-group" ng-repeat="(i, name) in name_list track by $index">
<div class="row">
<div class="col-xs-12">
<input class="form-control" type="text" ng-model="data.name_list[i]" add-input/>
</div>
</div>
</div>
Once addInput detects it is dirty, call parent directive controller:
if (dirty)
collectInput.reportInput();
JS:
directive('collectInput', function() {
return {
restrict: 'A',
controller: function($scope) {
var dirtyCount = 0;
this.reportInput = function() {
var count = $scope.name_list.length;
dirtyCount++;
if (count === dirtyCount) {
$scope.name_list.push('aaa');
}
}
},
}
}).
directive('addInput', ['$compile', '$sce', function ($compile, $sce) {
return {
restrict: 'A',
require: ['^collectInput', '?ngModel'],
link: function (scope, element, attrs, ctrls) {
var collectInput = ctrls[0]
var ngModel = ctrls[1];
scope.inputCounter = scope.name_list.length;
scope.$watch(
function(){
return ngModel.$dirty
},
function(dirty_val){
if (dirty_val){
collectInput.reportInput();
}
}
);
}
}}]);
I have a few radio buttons with certain value. What I'm trying to achieve is, on selecting certain radio buttons, it's value should add up and be displayed as total.
Here is my AngularJS directive and controller code :
angular.module('mapp',[])
.controller('ctrl',['$scope',function($scope){
$scope.items = [
{'Id':1, 'Cost':100},
{'Id':2,'Cost':200}
];
$scope.total = 0;
}])
.directive('customElement',function(){
return {
restrict: 'E',
scope:{
data: '=info'
},
template: '<input type="radio" ng-model="data">\
<span>{{data}}</span>'
}
});
And here is the HTML code:
<div ng-app="mapp">
<div ng-controller="ctrl">
<custom-element ng-repeat="item in items" info="item.Cost"></custom-element>
<br/>
<br/> Total: <span>{{total}}</span>
</div>
</div>
And here is a DEMO.
You can do that by passing in two different arguments to the directive: data (for the label) and then a secondary boolean selected to determine whether the item is selected or not.
Javascript:
angular.module('mapp',[])
.controller('ctrl',['$scope',function($scope){
$scope.items = [
{'Id':1, 'Cost':100, selected: false},
{'Id':2,'Cost':200, selected: false}
];
$scope.total = function () {
var selectedItems = $scope.items.filter(function (d) { return d.selected; });
console.log('items = ', $scope.items);
var totalSum = 0;
selectedItems.forEach(function (item) {
totalSum += item['Cost'];
});
return totalSum;
};
}])
.directive('customElement',function(){
return {
restrict: 'E',
scope:{
data: '=info',
selected: '=selected'
},
template: '<input type="radio" ng-model="selected" ng-value="true">\
<span>{{data}}</span>'
}
});
HTML:
<custom-element ng-repeat="item in items"
info="item.Cost"
selected="item.selected">
</custom-element>
Finally, you'll need to calculate the total via a getter.
Demo: http://jsfiddle.net/vv46xs0c/
I haven't succeeded with radio buttons (I don't know much about this thing :-(, and I could not "uncheck" the radio buttons ), but I've succeeded with checkboxes
Here is your updated fiddle : http://jsfiddle.net/8kpddb92/4/
What did I have to change :
ng-model needed a boolean
adding a function inside your controller
$scope.handleChange = function(){
$scope.total = 0;
for (var i=0; i < $scope.items.length; i++){
if ($scope.items[i].isSelected)
$scope.total += $scope.items[i].Cost;
}
}
And calling this function inside the child directive :
template: '<input type="checkbox" ng-model="data.isSelected" ng-change=$parent.handleChange()>\
<span>{{data.Cost}}</span>'
No need to make a new scope. Just use the 'item' from the repeat. Call a change function on click, pass the item, and you are good to go :)
angular.module('mapp',[])
.controller('ctrl',['$scope',function($scope){
$scope.items = [
{'Id':1, 'Cost':100},
{'Id':2,'Cost':200}
];
$scope.total = 0;
$scope.change = function(item) {
$scope.total = item.Cost;
};
}])
.directive('customElement',function(){
return {
restrict: 'E',
template: '<input type="radio" name="radios" ng-click="change(item)"><span>{{item.Cost}}</span>'
}
});