AngularJS Checkbox retain check value when the page reloads - javascript

I have a search screen with a checkbox, and want to retain the checkbox selection when the user navigates away and comes back to the screen.
Using the session storage, i am able to retain the value in the model, but the checkbox checked does not display correct based on the model value.
When I search online, it looks like i cannot use ng-model and ng-checked together. But I don't want to use jquery either.
Is it possible to do this with just Angular? Thanks in Advance.
<div class="container" ng-controller="SearchController as vm" data-ng-init="vm.init()">
<form ng-submit="vm.Search()">
<input type="checkbox" id="chkActive" name="chkActive" value="Active" ng-model="vm.searchInput.active" ng-checked="vm.searchInput.active" /> <span>Show Active Records</span>
<button id="searchBtn" type="submit">
</form>
</div>
Angular Controller Code:
vm.searchInput = { active: true};
vm.init = function () {
if ($window.sessionStorage.getItem("Search_Active")) {
vm.searchInput.active = $window.sessionStorage.getItem('Search_Active'); }
}
vm.Search = function () {
$window.sessionStorage.setItem('Search_Active', vm.searchInput.active);
}

I haven't checked it, but I'm sure the first line should read:
vm.searchInput = { active: true};

If the model value is there, you want to bind to it, and you know it's good then why would you need both checked and model? Binding the value to the input is enough. As you can see below, using both is problematic.
angular.module('app', []);
angular.module('app').controller('c', c);
function c() {
var self = this;
self.checked = true;
}
<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 "app" ng-controller="c as ctrl">
<div>
<label>Checked</label>
<input type="checkbox" ng-model="ctrl.checked" />
<div>
<span>Checked: {{ctrl.checked}}</span>
</div>
</div>
<div>
<label>Checked Trouble</label>
<input type="checkbox" ng-model="ctrl.checked" ng-checked="!ctrl.checked" />
<div>
<span>Checked: {{ctrl.checked}}, !Checked: {{!ctrl.checked}}</span>
</div>
</div>
<div>
<label>Checked Double Trouble</label>
<input type="checkbox" ng-checked="!ctrl.checked" ng-model="ctrl.checked" />
<div>
<span>Checked: {{ctrl.checked}}, !Checked: {{!ctrl.checked}}</span>
</div>
</div>
</div>

Related

AngularJS: Target a form with Controller As syntax in an object

Note: I did look around here on SO for solutions, yet no one had the additional issue of the function being in an object.
I have a form in my Angular JS app:
<div ng-app="plunker">
<div ng-controller="PMTController as pmt">
<form name="myForm">
<div class="form-group">
<input type="text" class="form-control" />
</div>
<button class="btn btn-primary" ng-click="pmt.search.resetSearchForm()">Reset</button>
</form>
</div>
</div>
Further, I have a controller with an object:
app.controller('PMTController', function($log) {
var _this = this;
_this.search = {
resetSearchForm: function () {
$log.debug('test');
// how to target the form?
}
};
})
My ng-click works, as the log.debug works. But no amount of tweaking to target the form so that I can reset the entire thing (empty all the fields) works.
I can do $window.myForm.reset(); but how could I do this from angular?
Note please my main issue/question is how to correctly target the form from inside that resetSearchForm function in the search object.
Note I tried changing the form name to pmt.myForm or pmt.search.myForm to no avail.
I tried $setPristine and $setUntouched() but they don't seem to clear the fields.
I know I can assign a model and assign it to all the form controls, but this is for a prototype so I'd rather do a simple reset.
I made a pen: https://codepen.io/smlombardi/pen/YWOPPq?editors=1011#0
Here is my take on your codepen that will hopefully resolve the issue:
https://codepen.io/watsoncn/pen/YWOXqZ?editors=1011
Explanation:
Angular's documentation provides an example of a "Form Reset" button, but you can apply the same logic towards resetting after submission:
Documentation:https://docs.angularjs.org/guide/forms
with a plunker:
Live Example:https://plnkr.co/edit/?p=preview
The example shows the use of Angular's copy method that creates a deep copy of whatever you pass it as a parameter and assigns it to the ng-model that is put on a particular input field. In this case they simply pass it an empty master object.
You need to make sure to add an ng-model attribute to your inputs, then create a reset function that can run after submission. Another common option would be to simply set each input's ng-model to empty strings in the submission function, such as $scope.inputModel = ""
Is this what you were hoping for? I might have misunderstood the question. I will happily take another crack at it if there is still confusion.
To get the form in your controller you just need to name your form this way:
<form name="pmt.myForm">
Here's a complete demo:
(function() {
"use strict";
angular
.module('plunker', [])
.controller('PMTController', PMTController);
PMTController.$inject = ['$log'];
function PMTController($log) {
var _this = this;
_this.model = {};
_this.search = {
resetSearchForm: function() {
console.log(_this.myForm); // -> Form reference
_this.model = {};
}
};
}
})();
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body ng-controller="PMTController as pmt">
<div class="col-md-12">
<form name="pmt.myForm">
<div class="form-group">
<input type="text" ng-model="pmt.model.example" class="form-control" />
<input type="text" ng-model="pmt.model.example2" class="form-control" />
<input type="text" ng-model="pmt.model.example3" class="form-control" />
</div>
<button class="btn btn-primary" ng-click="pmt.search.resetSearchForm()">Reset</button>
</form>
<hr> All fields:
<pre ng-bind="pmt.model | json"></pre>
</div>
</body>
</html>

Angular checkboxes disapear on select

I have a list of checkboxes in my app:
<div class="col-md-6" ng-repeat="item in segment.items">
<div class="checkbox">
<label>
<input
type="checkbox"
ng-model="item"
ng-checked="item.enabled"
value="{{item.id}}"
class="segment-visibility-checkbox"
/>
{{item.name}} <code>/ {{item.slug}}</code>
</label>
</div>
</div>
The data, that exists on the $scope as segment.items, looks something like this:
[
{"id":1,"slug":"nl","name":"Dutch","enabled":true},
{"id":4,"slug":"en","name":"English","enabled":false},
{"id":2,"slug":"fr","name":"French","enabled":true},
{"id":3,"slug":"de","name":"German","enabled":false}
]
This renders fine on load, and the correct checboxes are checked. However, if I select a checkbox, the label disappears and the binding appears to be lost. If I deselect a checkbox, it seems to work fine, but if I select it again, it disappears as well. No errors show up in the console.
This is what it looks like on load:
And as soon as I click on "English" I get this
I'm new to Angular so I suspect I am doing something obvious wrong. Can anybody please point me in the right direction?
pointing your ng-model to ng-model="item" will cast your item into a boolean.
Also, you should not use ng-model with ng-checked : https://docs.angularjs.org/api/ng/directive/ngChecked
what you should do is the following :
<input
type="checkbox"
ng-model="item.enabled"
value="{{item.id}}"
class="segment-visibility-checkbox"
/>
You need to bind the ng-model directly on your enabled boolean attribute:
<input
type="checkbox"
ng-model="item.enabled"
value="{{item.id}}"
class="segment-visibility-checkbox"
/>
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.segment = {
items: [
{"id":1,"slug":"nl","name":"Dutch","enabled":true},
{"id":4,"slug":"en","name":"English","enabled":false},
{"id":2,"slug":"fr","name":"French","enabled":true},
{"id":3,"slug":"de","name":"German","enabled":false}
]
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
{{segment.items}}
<div class="col-md-6" ng-repeat="item in segment.items">
<div class="checkbox">
<label>
<input
type="checkbox"
ng-model="item.enabled"
value="{{item.id}}"
class="segment-visibility-checkbox"
/>
{{item.name}} <code>/ {{item.slug}}</code>
</label>
</div>
</div>
</div>

Access "calling scope" and strange behaviour

I have a simple snippet of code :
function SomeCtrl($scope) {
$scope.modify = function(value) {
$scope.something = "Hello";
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="SomeCtrl">
<div ng-repeat="toto in [1,2,4,5]">
<input ng-model="something" />
<input ng-model="something" />
<button ng-click="modify()">Modify</button>
</div>
</div>
</div>
Does anyone can explain how I could change it so the modify() function only change the textfields inside the scope of the button I click ?
I also don't get why only the text fields which have not been edited are modified by the function.
Thank you very much
This is because ng-repeat creates it's own scope. Using prototypal inheritance. By declaring ng-model you're creating a new field on that new scope.
But this will work for what you're trying to do.
<div ng-repeat="toto in [1,2,4,5]" ng-init="something = {}">
<input ng-model="something.hi" />
<input ng-model="something.hi" />
<button ng-click="modify(something)">Modify</button>
</div>
</body>
.controller('ctrl', function ($scope) {
$scope.modify = function (something) {
something.hi = "hello";
}
})
In this case you are just pushing out on screen the same info for times, meanwhile binding everything to the same variable. You can just simply create array and bind every input line to appropriate array element. And by pressing "modify" button, pass parameter, witch array element must be changed.
function SomeCtrl($scope) {
$scope.something = [];
$scope.modify = function(toto) {
$scope.something[toto] = toto;
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="SomeCtrl">
<div ng-repeat="toto in [1,2,4,5]">
<input ng-model="something[toto]" />
<input ng-model="something[toto]" />
<button ng-click="modify(toto)">Modify</button>
</div>
</div>
</div>

Angularjs keep the focus on a field after ng-click?

I try to figure out how I can keep the focus on an input field in angularjs after I click on a button.
My goal is to prevent my mobile to hide his keyboard right after I click on the + button. I want to keep the focus on input choice.
Like this the user can add a new choice without the need to click again on my input.
<div id="demo" ng-app="Foobar">
<div ng-controller="DemoCtrl">
<input type="text" ng-model="title" placeholder="title" />
<input type="text" ng-model="choice" placeholder="choice" />
<button ng-click="addChoice(choice)">+</button>
{{choices}}
</div>
</div>
angular.module('Foobar', [])
.controller('DemoCtrl', ['$scope', function ($scope) {
$scope.choices = [];
$scope.addChoice = function (choice) {
$scope.choices.push(choice);
};
}]);
http://jsfiddle.net/gbg09bto/
What is the best strategy ? (directive, ng-focus)
simplest thing is do it by plain javascript
to do it
in html // put a id attribute
<input type="text" id="choice" ng-model="choice" placeholder="choice" />
in controller function
$scope.addChoice = function (choice) {
$scope.choices.push(choice);
document.getElementById("choice").focus(); // get the element by id & focus the input
};
here is the updated Fiddle

How to access an array of ID using an event trigger with checkboxes?

I need your help with my problem.
I created a static form. With a lots of and checkboxes. My problem is, I am integrating a javascript code for the selection of checkboxes. When the user check the parent checkboxes it will automatically check the subcategory. I can do this one by one (hardcoded). But it is a lot of work. What I think is I will put all of the IDs in an array and create a loop or event that will access them. But I don't know how. Ok that's all.
Here's my code: I am using CI and jquery 1.5
//here's the array
var checkboxParentMenu = ["checkAllFilipino","checkAllContinental","checkAllAsian","checkAllOthers"];
var checkboxChildMenu = ["filipino_cat","continental_cat","asian_cat","others_cat"];
Now here's the manual way.
$("input[data-check='checkAllFilipino']").change(function(){
$("#filipino_cat").find("input[type=checkbox]").attr("checked",this.checked);
});
Here's the pattern sample
<div id="parentTab">
<div id="categoryTab">
<input type="checkbox" />
</div>
<div id="subCategoryTab">
<input type="checkbox" />
</div>
<div id="childOfSubCategory">
<input type="checkbox" />
</div>
....
</div>
The super easy way out would be to actually nest the divs, then you could do this:
$('input[type=checkbox]').click(function () {
$(this).parent().find('input[type=checkbox]').attr('checked', $(this).attr('checked'));
});
HTML:
<div id="parentTab">
<div id="categoryTab">
<input type="checkbox" />
<div id="subCategoryTab">
<input type="checkbox" />
<div id="childOfSubCategory">
<input type="checkbox" />
</div>
</div>
</div>
</div>
One easy way out is
var checkboxParentMenu = ["checkAllFilipino", "checkAllContinental", "checkAllAsian", "checkAllOthers"];
var checkboxChildMenu = ["filipino_cat", "continental_cat", "asian_cat", "others_cat"];
$.each(checkboxParentMenu, function (idx, name) {
$('input[data-check="' + name + '"]').change(function () {
$("#" + checkboxChildMenu[idx]).find("input[type=checkbox]").attr("checked", this.checked);
});
})
But I would recommend
<input type="checkbox" data-check="checkAllFilipino" data-target="#filipino_cat" />CHECK ALL
<br/>
then
$('input').filter('[data-check="checkAllFilipino"], [data-check="checkAllContinental"], [data-check="checkAllAsian"], [data-check="checkAllOthers"]').change(function () {
$($(this).data('target')).find("input[type=checkbox]").attr("checked", this.checked);
});
Demo: Fiddle
Use prop() in place of attr() like,
var checkboxParentMenu = ["checkAllFilipino","checkAllContinental","checkAllAsian","checkAllOthers"];
var checkboxChildMenu = ["filipino_cat","continental_cat","asian_cat","others_cat"];
$.each(checkboxParentMenu ,function(i,parentChk){
$("input[data-check='"+parentChk+'").on(change',function(){
$('#'+checkboxChildMenu[i]).find("input[type=checkbox]").prop("checked",this.checked);
});
});

Categories