Toggle true/false through radio buttons in AngularJS (inside of ng-repeat) - angularjs

Hej, I've got an "almost" working fiddle. I have a list of items and I want to change their value if their radiobutton is selected. Here's the code:
CodePen:
http://codepen.io/anon/pen/MyvQoP
Html:
<div ng-app="myapp" ng-controller="myController">
<div ng-repeat="food in foodList">
<span>{{food.name}}</span>
<input type="radio" ng-model="food.selected" name="radiofood" ng-value="true">
</div>
</div>
JS:
angular.module('myapp', []).controller("myController", myController)
function myController($scope) {
$scope.foodList = [
{
name: 'banana',
selected: 'false'
},
{
name: 'orange',
selected: 'false'
},
{
name: 'apple',
selected: 'false'
}
]
}
The problem:
A radiobutton once clicked, changes it's value to true but clicking another one does not change the previous one to false. So if you click each one of them, one by one, all of them will be true. I only want one to have the true value.
Thanks
--- Edit 2016-03-31 ---
I was looking for a solution without writing a custom fuction but it turns out this can't be done. I've marked #Ankit Pundhir answer as the best one but it wasn't exaclty what i was aiming for.

Add method to controller file:
$scope.selectFood = function(selectedFood){
angular.forEach($scope.foodList,function(food){
if(food != selectedFood){
food.selected = false;
}
})
};
and add ng-change="selectFood(food)" to radio button.

The most simple solution is to add ng-change event on the input and then write a function which takes selectedFood as param and do the following:
Iterates through foodList and changes every value to false
Toggle status of selectedFood (if true set false end vice versa)
Something like this:
$scope.toggleParam = function(selectedFood){
loopThroughAndSetToFalse();
findAndSetReverseValue(selectedFood);
}
function loopThroughAndSetToFalse(){
for(var i=0; i<$scope.foodList.length; i++){
$scope.foodList[i].selected = false;
}
}
function findAndSetReverseValue(selectedFood){
for(var i=0; i<$scope.foodList.length; i++){
if($scope.foodList[i].name === selectedFood.name){
$scope.foodList[i].selected = !(selectedFood.selected);
}
}
}
And your html now will look like this:
<div ng-app="myapp" ng-controller="myController">
<div ng-repeat="food in foodList">
<span>{{food.name}}</span>
<input type="radio" ng-model="food.selected" name="radiofood" ng-change="toggleParam(food)" ng-value="true">
</div>
<br><br>
{{foodList[0]}}<br>
{{foodList[1]}}<br>
{{foodList[2]}}
</div>

Related

How Can i do Only one checkbox selected at a time in given list in ngFor in angular 5?

I want to do only one checkbox selected at a time in ngFor in angular 5.
i have the following code below.
<div class="form-check" style="margin-top:0;">
<label class="form-check-label">
<input class="form-check-input" id="res{{restaurant._id}}" (change)="selectRestaurant(restaurant,i)" [checked]="restaurant.checked" type="checkbox">
<span class="form-check-sign"></span>
</label>
</div>
And in my component
selectRestaurant(restaurant: any, i: any) {
if (restaurant) {
restaurant.checked = !restaurant.checked;
}
}
So any possible solution for only one checkbox selected in given list?
You have to bind the checkbox item with ngmodel to the specific instance in for loop.
This you can try with ReactiveForms. See one example https://stackblitz.com/angular/ayqnbvbkmpy
I saw many examples with loop using. But I`am think its bad idea when checkboxes are too many. I recommend to use another way.
Create variable to contain checkbox index.
public checkboxIndex = 0; //default value for checking
public checkboxModel = [];
ngOnInit() {
for (let i = 0; i < checkboxCount.length; i++) {
this.checkboxModel.push({ name: `${i}`, enabled: false });
}
public checkboxChange(index) {
if (this.checkboxIndex !== index) {
this.checkboxModel[this.checkboxIndex].enabled = false;
}
this.checkboxIndex = index;
}
//HTML
<div *ngFor="let checkbox of checkboxCount.length; let i = index">
<input type="checkbox" [(ngModel)]="checkboxModel[i].enabled"
name="checkboxModel[i].name"
(change)="checkboxChange(i)"> </input>
</div>
It should help. Please correct me if I made some mistakes.

Remove empty option in the select using ng-model

I am new to angular js. In my code user changes the value of radio buttons. And depending on the value of the selected radio button, a piece of code is loaded from the ng-switch
HTML:
<body ng-app="">
<div ng-repeat="button in modes">
<label>
<input type="radio" ng-model="data.mode" value="{{button.value}}" ng-click="clearObjectIdModal()" name="e_modes">
{button.label}}
</label>
</div>
<div ng-switch on="data.mode">
<div ng-switch-when="client">
<label for="e_selected_object_item_id">Select Client name: </label>
<select id="e_selected_object_item_id" name="e_selected_object_item_id" ng-model="currentDataItem.object_id" required>
<option ng-repeat="item in customersListArr" value="{{ item.id }}">{{ item.Name }}</option>
</select>
</div>
<div ng-switch-when="agent">
// This part is similar to the previous one
</div>
</div>
</body>
Controller part:
$scope.data = {};
$scope.setFile = function () {
if ($scope.data.mode == 'client')
return 'client';
else if ($scope.data.mode == 'agent')
return 'agent';
$scope.modes = [{
value: 'client',
label: 'Client'
},{
value: 'agent',
label: 'Agent'
}];
$scope.currentDataItem = data; // data is preloaded from inputs in form
There is also a ng-click="clearObjectIdModal()" that clears the model when switching radio buttons:
$scope.clearObjectIdModal = function() {
$scope.currentDataItem = "";
}
The problem is that every time when the radio button is switched to the select value, which dynamically changes, the value of the first option in it becomes equal to undefined. Because in the array from where these options are built there is no such object_id (This is the id that is not there, so an empty field is drawn).
That is, there are all works. But the first option in the select(after switching to another radio button) is rendered as an empty string.
There are thoughts, how it can be fixed?
I'm not sure if I understand you problem correctly but I would suggest a few improvements.
change your setFile function to as follows
$scope.setFile = function (){return $scope.data.mode;}
I also do not see the closing brackets for your function in your code. Besides if your function will only return the data.mode then why need the function?
I would suggest initialize your data object properly like:
$scope.data = {mode:'client'};
Change your clearObjectIdModal function as:
$scope.clearObjectIdModal = function(mode)
{
$scope.currentDataItem = "";
$scope.data.mode=mode;
}
and in your HTML use it as ng-click="clearObjectIdModal(button.mode)"
So in function clearObjectIdModal() I wrote:
$scope.clearObjectIdModal = function() {
if ($scope.e_data["mode"] == 'client') {
if ($scope.customersListArr.length > 0) {
$scope.currentDataItem.object_id = $scope.customersListArr[0]['id'];
}
}
else if ($scope.e_data["mode"] == 'agent') {
if ($scope.agentsListArr.length > 0) {
$scope.currentDataItem.object_id = $scope.agentsListArr[0]['id'];
}
}
}
And after this when I change radio buttons the first option in current select(which every time is changed) will be not empty.
Also the problem with an additional empty option is possible to solve when you add a title as the first item in the list:
<option value="" disabled>Select</option>

Angular ng-if how do i reset the value of the model, in an angular way

<div ng-app>
<form ng-controller='chip'>
<select data-ng-options="n for n in simOptions" data-ng-model="simQuantity"></select>
<div ng-if="simQuantity>=1">
<select name="sim" ng-model="formData.sim[0]" ng-options="sim for sim in sims" ></select>
</div>
<div class="suscriptor_fields" ng-if="simQuantity>=2">
<select name="sim"
ng-model="formData.sim[1]"
ng-options="sim for sim in sims" ></select>
</div>
<div class="suscriptor_fields" ng-if="simQuantity>=3">
<select name="sim"
ng-model="formData.sim[2]"
ng-options="sim for sim in sims" ></select>
</div>
<div class="suscriptor_fields" ng-if="simQuantity>=4">
<select name="sim"
ng-model="formData.sim[3]"
ng-options="sim for sim in sims" ></select>
</div>
{{formData.sim}}
If in the first select i choose 2 to 4 and select a value in the second to fourth select options and then i reselect the first one with a lower value, the ng-if turns to false but the ng-model doesnt change i need to get it to null again, so if doesnt get sent when i submit the form. In a nutshell, if a user selects 2, will get two options, if he/she selects two options but then changes his/her mind and decides only wants 1, the field disappears but the value is still getting send when submit.
this is the fiddle
jsfiddle.net/U3pVM/13524/
and the javascript part
function chip($scope) {
$scope.formData = {
'sim' : {
'0' : null,
'1' : null,
'2' : null,
'3' : null
}
};
$scope.simQuantity = 1;
$scope.simOptions = [1,2,3,4];
$scope.sims = [
'Mini-SIM',
'Micro-SIM',
'Nano-SIM',
];
}
You can clean the data during ng-change to remove the extra properties.
I have cleaned up your jsfiddle that was not working and implemented a solution:
http://jsfiddle.net/k1m3cd60/
code:
$scope.clean = function(n) {
for (var i = 4; i >= +n; i--) {
delete $scope.formData.sim[i];
}
};
html:
ng-change="clean(simQuantity)"

Edit object inside array - AngularJS

http://jsfiddle.net/cnnMQ/2/
You can see here I have a pretty nice functioning Add/Remove/Edit functionality for removing objects from an array.
What I am struggling with is
Editing inline and pushing the changes back into the array.
Adding new input fields to the DOM in order to push new objects into the array.
http://jsfiddle.net/cnnMQ/2/
app = angular.module("sparta", []);
window.CompetitionController = function($scope) {
$scope.activities = [{
id: 6431,
name: "Meeting",
points: 20
}, {
id: 6432,
name: "Deal",
points: 100
}];
$scope.addNewActivity = function() {
//This function should create 2 new input fields
//The user should input the name and points
//We can ignore the id for now
//Then the object should be craeted and pushed in as you see below with the mock data.
var updatedActivities = {
id: 6433,
name: "Call",
points: 5
};
$scope.activities.push(updatedActivities);
}
$scope.editActivity = function(activity) {
var selectedActivity = activity;
console.log(selectedActivity);
}
$scope.removeActivity = function(activity) {
activityId = activity.id; //the activity id
var i = 0;
for (var item in $scope.activities) {
if ($scope.activities[item].id == activityId)
break;
i++;
}
$scope.activities.splice(i, 1);
}
}
The HTML is as follows:
<body ng-app="sparta">
<div class="container" ng-controller="CompetitionController">
<div ng-repeat="activity in activities">
{{activity.name}} - {{activity.points}}
<button ng-click="editActivity(activity)">Edit</button>
<button ng-click="removeActivity(activity)">Remove</button>
</div>
<div class="addNew">
<button ng-click="addNewActivity()">Add New</button>
</div>
</div>
</body>
I've tried to give as much as possible in the fiddle - what I would love is some guidance on the addNewActivity() function and the editActivity() function and how to inline edit the two input fields and save the changes back into the array.
Thanks in advance!
You can change your html from:
{{activity.name}} - {{activity.points}}
To:
<input type="text" ng-model="activity.name"/> - <input type="text" ng-model="activity.points"/>
So you get 2-way binding.
Working example: http://jsfiddle.net/CFx7m/
Here's another simple example: http://jsfiddle.net/A5xZ9/2/
Basically you hide input field until activity edit button is clicked, in which case you show input field and hide text:
<div ng-show="activity.isEdited">
<input type="text" ng-model="activity.name"/> - <input type="text" ng-model="activity.points"/>
<button ng-click="activity.isEdited = false">Ok</button>
</div>
<div ng-hide="activity.isEdited">
{{activity.name}} - {{activity.points}}
<button ng-click="activity.isEdited = true">Edit</button>
<button ng-click="removeActivity(activity)">Remove</button>
</div>
There's a lot of improvement possible, for example editing local copy of the activity and updating original attributes only when user presses Ok, and providing Cancel button as well.

Knockout.js Checkbox checked and click event

We're trying to implement a checkbox and list with the following functionality:
Clicking the checkbox will either clear the array if there are items in there, or add a new item if not.
Remove an item from the array when clicking the Remove button, once the last item is removed the checkbox automatically unchecks itself.
The problem I am having is that if you click to remove each array item, then click the checkbox to add a blank entry, I'm expecting the checkbox to be checked again (as per the checked observable), however it is not?
I have the following code:
http://jsfiddle.net/UBsW5/3/
<div>
<input type="checkbox" data-bind="checked: PreviousSurnames().length > 0, click: $root.PreviousSurnames_Click" />Previous Surname(s)?
</div>
<div data-bind="foreach: PreviousSurnames">
<div>
<input type="text" data-bind="value: $data">
<span data-bind="click: $root.removePreviousSurname">Remove</span>
</div>
</div>
var myViewModelExample = function () {
var self = this;
self.PreviousSurnames = ko.observableArray(['SURNAME1', 'SURNAME2', 'SURNAME3']);
self.removePreviousSurname = function (surname) {
self.PreviousSurnames.remove(surname);
};
self.PreviousSurnames_Click = function () {
if (self.PreviousSurnames().length === 0) {
self.PreviousSurnames.push('');
}
else {
self.PreviousSurnames.removeAll();
}
alet(2)
}
}
ko.applyBindings(new myViewModelExample());
If you are using together the click and the checked then you need to return true from your click handler to allow the browser default click action which is in this case checking the checkbox:
self.PreviousSurnames_Click = function () {
if (self.PreviousSurnames().length === 0) {
self.PreviousSurnames.push('');
}
else {
self.PreviousSurnames.removeAll();
}
return true;
}
Demo JSFiddle.
You need to use a computed to monitor the length of the observable array. This way when the length reaches zero you can react to it automatically.
self.surnames = ko.computed(function() {
var checked = true;
if (self.PreviousSurnames().length === 0) {
self.PreviousSurnames.push('');
checked = false;
}
return checked;
});
Now you will have the blank text box when all of the names are cleared. If you update your binding on the checkbox it will function properly as well.
<input type="checkbox" data-bind="checked: surnames, click: PreviousSurnames_Click" />Previous Surname(s)?
FIDDLE

Resources