Using a group of checkboxes in Angularjs - angularjs

Im having the following problem:
i have a group of checkboxes and an indifferent check too, in the database if indifferent is checked then an empty array is saved.
I have 2 use cases:
1) if indifferent is checked, the rest is not, as soon as i check another checkbox indifferent is unchecked (This is actually working)
2) if i select all checkboxes (except indifferent), all should be unchecked and indifferent should be checked. (This is not working)
Here is an extract of my code
http://jsfiddle.net/ngbYW/
1) To test first use case:
Indifferent is checked, as soon as you click Married, indifferent is unchecked, if u click again on Married to uncheck, indifferent is checked.
2) click on Single, Relationship and Married to get them checked, then indifferent is checked AND the last one where u clicked is checked too!
Hope im clear enough.
What im doing wrong? Any help or suggestion will be appreciated.
Here is my code
HTML
<div ng-app="">
<div ng-controller="MyCntrl">
<label class="control-label">Family status</label>
<div class="controls">
<label class="checkbox inline" ng-repeat="item in familystatus"><input type="checkbox" ng-click="addToSearchedProfile(item.id,'familystatus')" ng-checked="isChecked(item,'familystatus')" >{{item.text}}</label>
<label class="checkbox inline"><input type="checkbox" value="" ng-click="addToSearchedProfile(undefined,'familystatus')" ng-checked="userSearchedProfile.familystatus.length=='0'">indifferent</label>
</div>
<label class="control-label">Sexuality</label>
<div class="controls">
<label class="checkbox inline" ng-repeat="item in sexuality"><input type="checkbox" ng-click="addToSearchedProfile(item.id,'sexuality')" ng-checked="isChecked(item,'sexuality')" >{{item.text}}</label>
<label class="checkbox inline"><input type="checkbox" value="" ng-click="addToSearchedProfile(undefined,'sexuality')" ng-checked="userSearchedProfile.sexuality.length=='0'">indifferent</label>
</div>
</div>
</div>
CONTROLLER
function MyCntrl($scope) {
$scope.familystatus = [{id:1,text:'Heterosexual'},{id:2,text:'Bisexual'},{id:3,text:'Homosexual'}];
$scope.sexuality = [{id:1,text:'Single'},{id:2,text:'Relationship'},{id:3,text:'Married'}];
$scope.userSearchedProfile = {
familystatus : [1],
sexuality : []
};
$scope.isChecked = function(item, type) {
return $scope.userSearchedProfile[type].indexOf(item.id)!==-1;
};
$scope.addToSearchedProfile = function(id, item) {
if (angular.isUndefined(id)) {
$scope.userSearchedProfile[item].length=0;
return;
}
if ($scope.userSearchedProfile[item].indexOf(id) === -1) {
$scope.userSearchedProfile[item].push(id);
} else {
$scope.userSearchedProfile[item].splice($scope.userSearchedProfile[item].indexOf(id), 1);
}
if ($scope[item].length === $scope.userSearchedProfile[item].length){
$scope.userSearchedProfile[item].length=0;
}
};
}

inter-restricting / counter acting form elements are very confusing
to me too.
I usually attack this kind of problem by defining a view model
which represents the form state and let javascript code to handle
the coordination rather than reacting to the indivisual events.
here is the simplified example: http://jsfiddle.net/4TBFn/
in template:
<label class="checkbox inline" ng-repeat="item in sexuality">
<input type="checkbox" ng-model="item.selected"/>{{item.text}}
</label>
<label class="checkbox inline">
<input type="checkbox" ng-model="indifferent"/>indifferent
</label>
in controller:
$scope.$watch('indifferent', function(v) {
if (!v) return;
for ( var i = 0; i < $scope.sexuality.length; ++i ) {
$scope.sexuality[ i ].selected = false;
}
});
$scope.$watch('sexuality', function(arr) {
var selected = arr.reduce(function(s, c) { return s + (c.selected ? 1 : 0); }, 0);
if ( selected === arr.length ) {
$scope.indifferent = true;
} else if ( selected > 0 ) {
$scope.indifferent = false;
}
}, true );

Related

checkbox checked attribute not working in reactJS

I have a radio button that I am rendering dynamically, But the checked property is not working.
Below is my code.
case "6":
var vchky = "";
var vchkn = "";
if(item.answer === "Yes"){
vchky= true;
vchkn = false;
}
else if(item.answer === "No"){
vchky= false;
vchkn = true;
}
console.log("vchky : ", vchky);
console.log("vchkn : ", vchkn);
return (
<li key={key}>
<div class="custom-selection ml-0 pl-0">
<p>{item.questionText}</p>
<span class="ml-10">
<input type="radio" class="custom-control-input" id="customRadio1-11" name="ques-1"
disabled="disabled"
checked = {vchky}
value = "Yes"
/>
<label class="custom-control-label" for="customRadio1-11">Yes</label>
</span> <span>
<input type="radio" class="custom-control-input" id="customRadio2-22" name="ques-1"
checked = {vchkn}
disabled="disabled"
value = "No"
/>
<label class="custom-control-label" for="customRadio2-22">No</label>
</span> </div>
</li>
);
break;
I debugged and checked that item.answer = "Yes" , but radiobutton for Yes is notting getting checked.
when I inspected the element, there too the checked attribute is present but not getting rendering.
check below screenshot.
What am I missing? thanks.

ng model not updating in radio button group with ng-repeat

I am displaying radio buttons based on search result using ng-repeat.
if i select any radio button, its color will change.
actual issue is, when i do second search, list will replace with new list.
but when i select any radion button its color not changed.
View:
<div class="col-md-4 col-sm-6 nl_item" ng-repeat="nomineeMgr in nomineesMgrList track by $index">
<div class="checkbox" ng-class="{'blue1': nomineeMgr.SystemUserId===nomManagerSelectedId}">
<label class="radio-inline">
<input type="radio" value="" name="selectedNomineeMgr{{$index}}"
ng-model="$parent.nomManagerSelectedId" ng-value="{{nomineeMgr.SystemUserId}}" />{{nomineeMgr.SystemUserId===nomManagerSelectedId?"SELECTED"}}
</label>
</div>
</div>
angular controller:
$scope.nomManagerSelectedId = 0;
$scope.searchNomineesManager = function (isValid) {
if (!isValid)
return;
var result = pepsicoService.getPepsicoEmployees($rootScope.UrlProvider.getPepsicoSearchEmployeesUrl, null, $scope.searchNomination.searchNomineMgr).then(function (response) {
if (response.data.success) {
$scope.nomineesMgrList = [];
$scope.nomManagerSelectedId = 0;
$scope.nomineesMgrList = response.data.EmployeeList;
}
else {
$rootScope.showFailureMsg(response.data.errorMessage);
}
});
};
any one have an idea to solve this issue?

How can I do event on text box in Angular?

I have a text box that show when I click on checkbox and I need to make an event on it that can make me bind it to object from DB
HTML:
<div ng-repeat="feture in featureEnumArray">
<input id="txtchkFet" type="checkbox" ng-model="feture.IsChecked" />
{{feture.DisplayText}}
<div ng-show="feture.IsChecked" >
<input class="form-control" type="text" ng-model="feture.Value" ng-change="getFeatureID(feture)" id="txtValue" placeholder="Type Feature Value" />
</div>
<div class="label label-danger" ng-show="feture.IsChecked && !feture.Value">
Type Value
</div>
</div>
And in Angular controller I did Like this :
$scope.getFeatureID = function (feture) {
if (feture.IsChecked) {
$scope.Planfeature = angular.copy(feture);
$scope.PlanFeatureTemp.FeatureID = $scope.Planfeature.ID;
$scope.PlanFeatureTemp.Value = $scope.Planfeature.Value;
$scope.Planfeature = [];
}
else {
var index = $scope.JAdminPlan.PlanFeatureValues.indexOf(feture);
$scope.JAdminPlan.PlanFeatureValues.splice(index, 1);
}
if (!$scope.$$phase) $scope.$apply();
};

Angular directive for horizontal Bootstrap form

I'm trying to build a directive for my Angular to help with the integration of form fields. I've implemented Scott Allens solution from his Angular playbook, and it works fine for a normal stacked form.
I need however to adapt it to a horizontal form instead. Here's my code:
Markup
<div form-group>
<label for="name">Name</label>
<input type="text" id="name" ng-model="vm.name">
</div>
formGroup directive
function link(scope, element) {
setupDom(element[0]);
}
function setupDom(element) {
var label = element.querySelector("label");
label.classList.add("control-label");
var input = element.querySelector("input, textarea, select");
var type = input.getAttribute("type");
if (type !== "radio" && type !== "checkbox"){
input.classList.add("form-control");
}
element.classList.add("form-group");
}
function formGroup() {
return {
restrict: "A",
link: link
}
}
The output becomes:
<div form-group="" class="form-group">
<label for="name" class="control-label">Name</label>
<input type="text" id="name" ng-model="vm.name" class="form-control">
</div>
And that's fine for stacked form. Since I need a horizontal form, my output needs to look like this:
<div form-group="" class="form-group">
<label for="name" class="control-label col-sm-3">Name</label>
<div class="col-sm-9">
<input type="text" id="name" ng-model="vm.name" class="form-control">
</div>
</div>
I've tried many solutions and I can get it work with single elements like an input, textarea or a select. It becomes much more tricky when I have something like two radio buttons inside my markup like this:
<div form-group>
<label>Active</label>
<div class="radio">
<label>
<input type="radio" name="active" ng-value="true" ng-model="vm.active"> Yes
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="active" ng-value="false" ng-model="vm.active"> No
</label>
</div>
</div>
The desired output of the above mentioned code should be:
<div form-group class="form-group">
<label class="control-label col-sm-3">Active</label>
<div class="col-sm-9">
<div class="radio">
<label>
<input type="radio" name="active" ng-value="true" ng-model="vm.active"> Yes
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="active" ng-value="false" ng-model="vm.active"> No
</label>
</div>
</div>
</div>
Please notice that the input(s) in the form-group is not fixed. It can be either a single input, textarea, select, a group of radio buttons or checkboxes. I'm lost for how I can make that happen. Any help is appreciated. Thanks!
UPDATE
I made some small changes to Mark Veenstra's code to make it (sort of) working:
function setupDom(element) {
element.classList.add("form-group");
var label = element.querySelector("label");
label.classList.add("control-label", "col-sm-3");
var input = element.querySelector("input, textarea, select");
var type = input.getAttribute("type");
if (type !== "radio" && type !== "checkbox"){
input.classList.add("form-control");
angular.element(input).wrap(angular.element('<div class="col-sm-9"></div>'));
}
var div_radio = element.querySelector("div[class='radio']");
angular.element(div_radio).wrap(angular.element('<div class="col-sm-9"></div>'));
}
This does not work completely as intended with multiple radio inputs since it only wraps the <div> on the first radio input element.
The output from radio button example in my original post using Marks code is:
<div form-group="" class="form-group">
<label class="control-label col-sm-3">Active</label>
<div class="col-sm-9">
<div class="radio">
<label>
<input type="radio" name="active" ng-value="true" ng-model="vm.active" value="true"> Yes
</label>
</div>
</div>
<div class="radio">
<label>
<input type="radio" name="active" ng-value="false" ng-model="vm.active" value="false"> No
</label>
</div>
</div>
SOLUTION
Check out the Plunker with the final result: http://plnkr.co/edit/Wv6V86hHTCz3URS9DhdU?p=preview
In the angular.element documentation you can find the method wrap() to be able to wrap HTML around a selected element. Or see this direct link.
So what you could do in your directive is change the setupDom() function to match your requirements per type of form element.
function link(scope, element) {
setupDom(element[0]);
}
function setupDom(element) {
element.classList.add("form-group");
var label = element.querySelector("label");
label.classList.add("control-label col-sm-3");
var input = element.querySelector("input, textarea, select");
var type = input.getAttribute("type");
if (type !== "radio" && type !== "checkbox"){
input.classList.add("form-control");
input.wrap(angular.element('<div class="col-sm-9"></div>'));
}
var div_radio = element.querySelectorAll("div[class='radio']");
div_radio.wrap(angular.element('<div class="col-sm-9"></div>'));
}
function formGroup() {
return {
restrict: "A",
link: link
}
}
NOTE: This code is not tested, maybe there are some minor mistakes, but I guess you'll get the point now.
Mark's suggestion came close, but it didn't solve my problem completely. I ended up using the following code in my formGroup directive:
(function (module) {
"use strict";
function link(scope, element) {
setupDom(element[0]);
}
function setupDom(element) {
element.classList.add("form-group");
var children = angular.element(element).children();
var labels = children.splice(0, 1);
// Set label classes
labels[0].classList.add("control-label", "col-sm-3");
// Wrap children in div
angular.element(children).wrapAll(angular.element("<div class='col-sm-9'></div>"));
// Handle inputs
var inputs = element.querySelectorAll("input, textarea, select");
for (var i = 0, len = inputs.length; i < len; i++) {
var input = inputs[i],
type = input.getAttribute("type");
if (type !== "radio" && type !== "checkbox") {
input.classList.add("form-control");
}
}
}
function formGroup() {
return {
restrict: "A",
link: link
}
}
module.directive("formGroup", formGroup);
}(angular.module("app.core")));
Check out this Plunker to see it in action: http://plnkr.co/edit/Wv6V86hHTCz3URS9DhdU?p=preview

Exclusive options in AngularJS

I have a list of checkbox and one of checkbox has value ALL. Whenever ALL is checked then the others of checkbox will be disabled and unchecked (value is empty). How should I do this in AngularJS? A list of checkbox is generated by using a loop over a data list as following:
<div ng-repeat="item in moduleService.elements">
<input type="checkbox">{{item.value}}
</div>
You could do something like this:
HTML:
<div ng-repeat="item in moduleService.elements">
<input id="{{'checkbox' + $index}}" type="checkbox" ng-disabled="allChecked" ng-model="item.isChecked">
<label for="{{'checkbox' + $index}}">{{item.value}}</label>
</div>
<div>
<input id="allCheckbox" type="checkbox" ng-model="allChecked" ng-click="onAllClicked()">
<label for="allCheckbox">All</label>
</div>
Controller:
var myCtrl = function(moduleService, $scope) {
$scope.onAllClicked = function() {
if(!$scope.allChecked) {
for (var i = 0; i < moduleService.elements.length; i++) {
moduleService.elements[i].isChecked = false;
}
}
}
}
Here is a JSFiddle with similar code: http://jsfiddle.net/robianmcd/W3xeP/
You can use ng-checked, and it makes it sexy.
<input type="checkbox" id="masterCheckbox" ng-model="master">
<div ng-repeat="item in moduleService.elements">
<input type="checkbox" ng-checked="master">{{item.value}}
</div>
Nice and easy and clean. Check out the JSFiddle
you would also need ng-disabled with Zack's answer
<input type="checkbox" id="masterCheckbox" ng-model="master">
<div ng-repeat="item in moduleService.elements">
<input type="checkbox" ng-disabled="master" ng-checked="master">{{item.value}}
</div>

Resources