Populate/clear array when checkbox checked/unchecked - javascript

I'm currently using angular-google-maps to build out a map with several different marker types. Below my map I have a simple set of checkboxes like so:
<div class="mapOptions">
<form action="" class="form-inline" style="text-align:center">
<label for="">General:</label>
<input type="checkbox" checked value="Games">
<label for="" style="color:#000033">Games</label>
<input type="checkbox" checked value="Practices">
<label for="" style="color:#ffd900">Practices</label>
</form>
</div>
Within my controller I initialize empty arrays then populate them with 'markers' through calls to my API endpoints:
vm.markersGames = [];
vm.markersPractices = [];
What I want to do is clear each respective array when its checkbox is unchecked (ex: User unchecks 'Games', method within my controller sets vm.markersGames = []), and re-populate each array when checkbox clicked (ex: User checks 'Practices', method within my controller calls API endpoint and populates vm.markersPractices).
The issue I've run into is not knowing how to properly add 'check/uncheck handlers' to my inputs.
Attempt to reload markers when checked:
vm.checkToggle = function(isChecked, value) {
if (!isChecked) {
vm[value] = [];
} else {
getPlayerAddress();
$scope.$apply();
}
};
getPlayerAddress() calls API to populate markers array.

You can use the ngChange directive in order to listen change on your input.
Here is an example :
Controller
(function(){
function Controller($scope, Service) {
//Object to know if the input is checked or not
$scope.form = {};
$scope.markersGames = [];
$scope.markersPractices = [];
//isChecked : input checked or not
//value : keyname of your array, for example markersGames
$scope.change = function(isChecked, value){
!isChecked
//If input is not checked, set our $scope[value] to empty array
? $scope[value] = []
//If the input is checked, call Service
: Service.get(value).then(function(data){
//Retrieve and set data
$scope[value] = data;
});
}
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
Then you can use a Service with promise to make your requests
Service
(function(){
function Service($q){
function get(url){
var defer = $q.defer();
var promise = defer.promise;
if (url === 'markersGames') {
defer.resolve([1,2,3,4]);
} else {
defer.resolve([4,6,8,1,5,2]);
}
return promise;
}
var factory = {
get: get
};
return factory;
}
angular
.module('app')
.factory('Service', Service);
})();
Then you can add ngChange directive in your html :
HTML
<body ng-app="app" ng-controller="ctrl">
<form action="" class="form-inline" style="text-align:center">
<label for="">General:</label>
<input type="checkbox" checked value="Games" ng-model="form.game" ng-change="change(form.game, 'markersGames')">
<label for="" style="color:#000033">Games</label>
<input type="checkbox" checked value="Practices" ng-model="form.practice" ng-change="change(form.practice, 'markersPractices')">
<label for="" style="color:#ffd900">Practices</label>
</form>
{{markersGames}}
{{markersPractices}}
</body>

Related

All the checkboxes inside a ng-repeat are getting checked when I select just one

I have list of objects named rolePermissionList like this:
[{"id":1,"name":"createUser","type":"user","marked":1},{"id":2,"name":"deleteUser","type":"user","marked":1},{"id":3,"name":"editRole","type":"role","marked":0}]
and I use ng-repeat to repeat checkboxes using the values in that list like this
<div class="form-group">
<label>Role Permissions:</label>
<div class="checkbox" ng-repeat="permission in rolePermissionList">
<label>
<input type="checkbox" ng-model="idsPermission[permission .idPermission ]"
ng-checked="permission.checked">{{permission.name}}
</label>
</div>
</div>
the ng-model of the checkboxes is named idsPermission and it's a list of numbers, those numbers are the IDS of the objects.
When I load the page the checkboxes that are supposed to be checked are checked this part works fine, but when I check another checkbox all the checkboxes gets checked, and when I uncheck a checkbox the same thing happens all the checkboxes gets unchecked.
I use that list of numbers named idsPermission to get all the IDS of the checkboxes that are checked, this worked before I used the directive ng-checked="permission.checked", but now I need to use it since now I need to show the checkboxes that are already marked.
this is my controller
angular.module('MyApp')
.controller('RolCtrl', ['$scope', 'RolService',
function ($scope, RolService) {
$scope.idsPermission = {};
$scope.getListCheckBoxesEditRole = function (idRole) {
$scope.selectRol.descripcion;
RolService.getListCheckBoxesEditRole(idRole)
.then(
function (d) {
var userPermissionList = [];
for (var permission in d) {
if (d[permission ].type === 'user') {
if (d[permission ].marked === 1)
{
d[permission ].checked = true;
userPermissionList.push(d[permission ]);
} else {
userPermissionList.push(d[permission ]);
}
}
}
$scope.rolePermissionList = userPermissionList;
},
function (errResponse) {
console.error('ERROR');
}
);
};
}
$scope.getListCheckBoxesEditRole(3);
]);
The RolService.getListCheckBoxesEditRole(idRole) service returns this JSON [{"id":1,"name":"createUser","type":"user","marked":1},{"id":2,"name":"deleteUser","type":"user","marked":1},{"id":3,"name":"editRole","type":"role","marked":0}]
and what I do in the controller is iterate over that list and check if the marked field is 1 if it's 1 I do this d[permission ].checked = true; I what I think that I do in that line is setting the checked value to true so I could use this directive in the html view ng-checked="permission.checked"
I tried doing this ng-checked="idsPermission[permission.checked]" but when I do this the values that are marked=1 in the JSON that I paste above don't appear checked when I load the page, but if I put it like this ng-checked="permission.checked" they appear marked as they should, but when I click a checkbox all the checkboxes gets selected.
I came across too many issues to document but the main problem was how you are iterating through the array that is returned from the service. It should be something like this:
Controller
angular.forEach(d.data, function(permission) {
if (permission.type === 'user') {
if (permission.marked === 1) {
permission.checked = true;
userPermissionList.push(permission);
} else {
userPermissionList.push(permission);
}
}
});
Then you can simplify your html like this:
HTML
<input type="checkbox" ng-model="permission.checked" />
You can see all of the changes in this working plunk.
I can't see in your code that $scope.idsPermission is getting defined. In ng-repeat you only set the key for the object but the value is undefined. That's why the checkbox won't show the correct value.
You could use ng-init to initialize the model. Please have a look at the simplified demo below or this fiddle.
(Also defining the models in your controller would be possible.)
Only using ng-model should be enough for the checkbox to work. I think I've read somewhere that ng-checked and ng-model aren't working smoothly together.
angular.module('demoApp', [])
.controller('mainCtrl', MainCtrl);
function MainCtrl() {
var vm = this;
angular.extend(vm, {
data: [{
id: 0,
marked: 1
}, {
id: 1,
marked: 0
}, {
id: 2,
marked: 1
}]
})
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="mainCtrl as ctrl">
<div ng-repeat="item in ctrl.data">
<input type="checkbox" ng-init="ctrl.idPermissions[item.id] = !!item.marked" ng-model="ctrl.idPermissions[item.id]"/>{{item.id}}
</div>
<pre>
permissions: {{ctrl.idPermissions | json: 2}}
data{{ctrl.data | json: 2}}</pre>
</div>

Fetch ids of all selected check boxes when one is selected or deselecte

Currently i'm making filter of products by country. I have list of countries with checkboxes, but i don't know how to properly fetch all ids if some one select a checkbox or de select it. Multiple selections of checkboxes are possible.
This is my HTML
<!--checkboxes-->
<fieldset class="m_bottom_15">
<legend class="default_t_color f_size_large m_bottom_15 clearfix full_width relative">
<b class="f_left">Filter by: country</b>
</legend>
<span ng-repeat="c in countries">
<input type="checkbox" ng-click="filter()" value="{{c.id_country}}" id="{{c.id_country}}"
class="d_none"><label for="{{c.id_country}}">{{c.country}}</label><br>
</span>
</fieldset>
And this is my controller
controllers.products = function($scope, categoriesFactory, productsFactory, countriesFactory, $routeParams){
var cat = $routeParams.param1;
productsFactory.getProductsInCategory($scope.subCategoryId).then(function(data){
$scope.products = data;
});
countriesFactory.getCountriesList().then(function(data){
$scope.countries = data.data;
})
}).error(function(e){
console.log(e);
});
//Filter products by country ids
//Don't know how to proceed!!
$scope.filter = function(id){
console.log(id);
}
}
My goal is to fetch all checked checkboxes whenever some one click on checkbox and store it in some json object or array so i can use it in api.
If you need any additional information, please let me know and i will provide.
You need to tie ngModel directive with <input type=checkbox> elements. Also use ngChange instead of ngClick. See: https://docs.angularjs.org/api/ng/input/input%5Bcheckbox%5D
For example:
<input type="checkbox" ng-change="filter()" ng-model="selectedCountries[c.id_country]">
Then in your controller:
$scope.selectedCountries = {};
$scope.filter = function() {
console.log(selectedCountries);
}

Angular: having a function as ng-false-value

In my Angular app, I have the following list of checkboxes, generated within a nested ng-repeat:
<div ng-repeat="partner in type.partners">
<label class="checkbox-inline">
<input type="checkbox"
ng-model="partners[$parent.$index][$index]"
ng-true-value="{{partner}}"
ng-change="handleCheckboxChanged({{type.id}})"
ng-checked="getChecked({{partner.id}})"
>
<p><span ></span>{{partner.name}}<p>
</label>
</div>
This will end up looking like the picture below:
When a user selects a partner with a chekcbox, this partner gets added to the nested list of selected partners, making use of ng-true-value and ng-model.
However, when a user deselects a checkbox, my object will still keep that key:value pair, except the value will now simply be false, as seen here in the console:
My intention would be that this key:value pair would disappear when a user unticks a checkbox, instead of it just becoming false.
Is it possible to do so by triggering a function as the ng-false-value?
What you described - this is a default behaviour. You can adjust your ngChange function.
Just a simple example, how you can make desired.
<div ng-repeat="partner in partners">
<label>
<input type="checkbox"
value="partner.id"
ng-model="partner.selected"
ng-change="changeValue(partner)"
/>
{{partner.name}}
</label>
</div>
var partnersList = [], idsArray = [];
$scope.changeValue = function(partner){
if(partner.selected)
addPartner(partner);
else
removePartner(partner);
};
var addPartner= function(partner){
if(!existInList(partner))
partnersList.push(partner);
};
var removePartner= function(partner){
idsArray = getIdsArray();
var indexToRemove = idsArray.indexOf(partner.id);
if(indexToRemove == -1)
return;
partnersList.splice(indexToRemove, 1);
};
var existInList = function(partner){
idsArray = getIdsArray();
return idsArray.indexOf(partner.id) != -1;
};
var getIdsArray = function(){
return partnersList.map(function(partner){ return partner.id });
};
Link to JSFiddle example.

How to get ng-repeat radio-button value inside the controller?

I have a form, within there are different input-tags and labels :
form action="">
<div class="fields" data-ng-repeat="option in question.body.options">
<input id="{{option.text}}" type="radio" name="gender" ng-model="demographic_value" ng-value="{{option.text}}">
<label for="{{option.text}}">{{option.text}}</label>
</div>
</form>
I want to access the value of the selected radio button, how is the data binded? Is there any standard-method, or "isChecked" value or something like that?
EDIT: OK, to be more clear: I want to have only the option which is selected. Inside the controller, not in the view.
So i can send the selected value over HTTP to a server.
Click a radio button
do something like var checked = $scope.radiobutton
array.push(checked)
Send over to a server
Use a shared service and inject it to any controllers:
angular.module("yourAppName", []).factory("mySharedService", function(){
var mySharedService = {};
mySharedService.values = {};
mySharedService.setValues = function(params){
mySharedService.values = params;
}
return mySharedService;
});
And after inject it into any controller.
For example:
function MainCtrl($scope, myService) {
$scope.radioButtons= myService.values;
}
function AdditionalCtrl($scope, myService) {
$scope.var= myService.values;
}
EDIT: as for checked/unchecked values:
You can use watcher:
$scope.$watch('question.body.options', function (changedOptions) {
//some actions with changed options
}, true);
UPDATE:
As for your update:
1) You should create watcher, such as above.
2) Into the watcher, when value changes - you initialize necessary service property with your values (call setValue function)
3) You should inject sharedService into another controller, and can get these values from this service.
4) Call $http or $resource method to sent this value on server.
ng-repeat creates its own scope for each item, so you might have problem accessing it. Try put the model in an object from parent scope.
ng-value accepts expression but not like {{expression}}.
http://jsfiddle.net/g8qLY/
HTML:
<form ng-app ng-controller="ctrl" name="inputform">
<label for="{{option}}" ng-repeat="option in options">
{{option}}
<input id="{{option}}" type="radio" name="gender"
ng-model="inputform.radioinput" ng-value="option">
</label>
<div ng-bind-template="Radio Input: {{inputform.radioinput}}"/>
</form>
JS:
function ctrl($scope) {
$scope.options = ['Option1', 'Option2', 'Option3'];
}

Sending POST with hidden <input> value does't work in AngularJs

In my web app, There are many form on a page. I want to submit it with AngularJS for specific form.
In each of form, it need unique ID with Hidden Value to submit. But value="UNIQUE_ID" seen doesn't work in hidden input box in AngularJS.
My HTML
<div ng-app>
<div ng-controller="SearchCtrl">
<form class="well form-search">
<input type="text" ng-model="keywords" name="qaq_id" value="UNIQUE_ID">
<pre ng-model="result">
{{result}}
</pre>
<form>
</div>
</div>
This is js script
function SearchCtrl($scope, $http) {
$scope.url = 'qa/vote_up'; // The url of our search
// The function that will be executed on button click (ng-click="search()")
$scope.search = function() {
// Create the http post request
// the data holds the keywords
// The request is a JSON request.
$http.post($scope.url, { "data" : $scope.keywords}).
success(function(data, status) {
$scope.status = status;
$scope.data = data;
$scope.result = data; // Show result from server in our <pre></pre> element
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
};
}
It may be that the only reason your code is not working is that $scope.keywords is a simple variable (with a text value) instead of an Object, which is required - see http://docs.angularjs.org/api/ng.$http#Usage
As angularJS works with variables within its own scope - its models, a form becomes just a way to interact with those models, wich can be sent via whatever method you want.
You can have a hidden field, yes, but in angularJS it isn't even necessary. You only need that information to be defined in the controller itself - randomly generated for each instance, or received from some other source.. Or you can define it yourself, upon the loading of the controller, for instance.
So (and only for sake of clarity) if you define a formData variable within your formCtrl:
Your HTML:
<div ng-app>
<div ng-controller="SearchCtrl">
<form class="well form-search">
<input type="text" ng-model="formData.title">
<input type="textarea" ng-model="formData.body">
<button ng-click="sendData()">Send!</button>
</form>
<pre ng-model="result">
{{result}}
</pre>
</div>
</div>
And your controller:
function SearchCtrl($scope, $http) {
$scope.url = 'qa/vote_up'; // The url of our search
// there is a formData object for each instance of
// SearchCtrl, with an id defined randomly
// Code from http://stackoverflow.com/a/1349426/1794563
function makeid()
{
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 5; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
$scope.formData = {
title: "",
text: ""
};
$scope.formData.id = makeid();
// The function that will be executed on button click (ng-click="sendData()")
$scope.sendData = function() {
// Create the http post request
// the data holds the keywords
// The request is a JSON request.
$http.post($scope.url, { "data" : $scope.formData}).
success(function(data, status) {
$scope.status = status;
$scope.data = data;
$scope.result = data; // Show result from server in our <pre></pre> element
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
};
}
Also: If you wanted to set the unique id on the html itself, you could add an input type="hidden" and set it's ng-model attribute to formData.id, and whichever value you set it to, the model would have it binded. using a hidden input won't work, as the value attribute doesn't update the angularJS Model assigned via ng-model. Use ng-init instead, to set up the value:
HTML with 2 forms:
<div ng-controller="SearchCtrl" ng-init="formData.id='FORM1'">
<form class="well form-search">
<input type="text" ng-model="formData.title">
<input type="textarea" ng-model="formData.body">
<button ng-click="sendData()">Send!</button>
</form>
</div>
<div ng-controller="SearchCtrl" ng-init="formData.id='FORM2'">
<form class="well form-search">
<input type="text" ng-model="formData.title">
<input type="textarea" ng-model="formData.body">
<button ng-click="sendData()">Send!</button>
</form>
</div>
You can add a hidden field, but it accomplishes nothing - the ng-init attribute does everything you need.

Categories

Resources