How to set radio button in angularjs with Object - angularjs

I have created radio buttons in angularjs using array of objects using ng-value and ng-model.
`
<div ng-controller="DemoController">
<div ng-repeat="detail in details">
<input type="radio" ng-model="$parent.selectedVal" ng-value="detail" name="test">
</div>
{{selectedVal}}
</div>
`
On selection of radio button model is populated with corresponding object value. But I am not sure how to initialize it using controller with object.
var app = angular.module('myApp', []);
app.controller("DemoController",DemoController);
function DemoController($scope) {
$scope.selectedVal={name:"Def",age:4} ;
$scope.details=[{name:'Abc',age:2},{name:'Xyz',age:3},{name:'Def',age:4}];
}

You should reference the selected value from the details array instead of creating a new instance:
$scope.details = [{ name:'Abc', age:2 }, { name:'Xyz', age:3 }, { name:'Def', age:4 }];
$scope.selectedVal = $scope.details[2];
This will select the last of the 3 radio buttons. Also if both details and selectedVal are defined within the same scope you should update your radio button as well, it's quite unclear why you referenced selectedVal from a $parentScope:
<input type="radio" ng-model="selectedVal" ng-value="detail" name="test" />
And here's the updated fiddle: https://jsfiddle.net/sb3krc8c/2/

Related

AngularJS how to bind select value in a ng-repeat directive?

currently struggling with a thing that I thought would be easy...
I'm trying to update a value in a ng-repeat directive using a select dropdown.
Here is what the HTML looks like:
<div ng-repeat="groupeQuestions in questionnaire.GroupesQuestions" class="umb-group-builder__group">
<select ng-model="groupeQuestions.TypeQuestionId" ng-options="value.Id as value.Description for value in typesQuestions ">
</select>
<input type="text" ng-model="groupeQuestions.TypeQuestionId"/>
<button ng-click="saveGroupeQuestions({{groupeQuestions}})" >Sauvegarder</button>
<button ng-click="deleteGoupeQuestions({{groupeQuestions.Id}})" >Supprimer</button>
</div>
And here is the js controller function used to update the item :
$scope.saveGroupeQuestions = function (groupeQuestions) {
console.log(groupeQuestions);
surveyPluginResource.saveGroupeQuestions(groupeQuestions).then(function (response) {
$scope.questionnaire = response.data;
navigationService.syncTree({ tree: 'survey', path: [-1, -1], forceReload: true }).then(function (syncArgs) {
navigationService.reloadNode(syncArgs.node);
});
});
};
Somehow, I'm missing something with the binding thing, because if I change the value in the dropdown, the textbox is updating as well.
But when it reaches the controller, the console.log() displays the item which does not contain the new groupeQuestions.TypeQuestionId.
I'm new to js and angularJs too, so is there something on binding that I've missed?
Don't use {{}} interpolation when passing a scope variable to a function
<button ng-click="saveGroupeQuestions(groupeQuestions)" >Sauvegarder</button>
<button ng-click="deleteGoupeQuestions(groupeQuestions.Id)" >Supprimer</button>

AngularJS - unchanged data passed by ng-model is interpreted as undefined instead of the value

I'm using Angular to generate some inputs and populate them with data using ng-repeat. I also want to bind the data inside the input to a save changes button which takes parameters provided by ng-model directives. save changes button prints the passed arguments using the built-in JS arguments object. For some reason, unless I change the text inside the input box, the output is [undefined, undefined]. Once I change the text inside the input boxes, the correct output is printed. Why is that?
JSfiddle code.
HTML:
<div ng-app="myApp" ng-controller="MainCtrl">
<p ng-repeat = "man in men">
<label>name</label><input type="text" ng-model="mname" ng-value="man.name"><br>
<label>status</label><input type="text" ng-model="mstatus" ng-value="man.status"><br>
<button ng-click="save(mname,mstatus)">
save changes
</button>
</p>
</div>
JS:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.men = [{
name: "jon snow",
status: "depands"
}, {
name: "rob stark",
status: "dead"
}];
$scope.save = function() {
console.log(arguments);
}
});
This is not recommended but for your specific requirement you can use ng-init to bind ng-value to your model
<p ng-repeat = "man in men">
<label>name</label><input type="text" ng-model="mname" ng-value="man.name" ng-init="mname = man.name"><br>
<label>status</label><input type="text" ng-model="mstatus" ng-value="man.status" ng-init="mstatus = man.status"><br>
<button ng-click="save(mname,mstatus)">
save changes
</button>
</p>
This wouldn't bind your changes to the original model.
Fiddle
ngModel doesn't update untill you use a key to change it, or set it from your controller. Because you are setting the field of the input using ngValue, it doesn't register to your ngModel untill you change it.
This problem is similar to how most datepickers don't work with ngModel, as they set the field with DOM-manipulation and NOT by inserting the value by "key".
You can easily fix this by using the following HTML instead:
<label>name</label><input type="text" ng-model="man.name"><br>
<label>status</label><input type="text" ng-model="man.status"><br>
I simply removed the ngValue and linked the ngModel to your "man".

Radio button and custom values in Angular JS [duplicate]

Using AngularJS, I would like to create a list of options with radio buttons, the last of which has an empty text field labeled 'Other' for inputing an option that is not in the list. Here's a demonstration of what I have in mind that I bootstrapped in CodePen. Since Stack Overflow insists on including CodePen code in this message, here it is:
js:
angular.module('choices', [])
.controller("MainCtrl", ['$scope', function($scope) {
$scope.color = '';
$scope.colors = [
"Red",
"Green",
"Blue",
"Other"
];
$scope.changeColor = function(){
$scope.color = "Red"
};
}]);
html:
<html>
<head>
<body ng-app="choices" ng-controller="MainCtrl">
<div ng-repeat="color in colors">
<input type="radio" ng-model="$parent.color" ng-value="color" id="{{color}}" name="color">
<label>
{{color}}
</label>
<input type="text" ng-model="$parent.color" ng-show="color=='Other'">
</div>
<p></p>
The chosen color is <strong>{{color}}</strong>
<p></p>
<button ng-click="changeColor()">Change color</button>
</body>
</html>
Here is what I want this demo app to do:
When I choose any option except for Other, the text field should remain blank;
If I place cursor in the text field, the option Other should be selected
Once I start typing in the text field, the option Other should remain selected
If I change the model that registers the options (in the demo app achieved by clicking the Change color button), the corresponding radio button should be selected.
I achieved most of that functionality by using three models (one for color, one for keeping track of radio buttons and one for the Other field) and three watchers, but the resultant app seems brittle and fails some of the tests. Could you please suggest a better way for creating such a selector in Angular using as few models and watchers as possible?
(My question is somewhat similar to this SO question, but I hope is different enough not to be considered a duplicate.)
Add a separate scope property for the other text:
$scope.other = '';
Add a colorChanged() method which will be called when the color is changed. This will set the other text to empty if color is not 'Other':
$scope.colorChanged = function () {
if ($scope.color != 'Other') {
$scope.other = '';
}
};
This will also need to be called from changeColor(). I ended up changing changeColor to allow the color to be passed in. It otherwise defaults to red:
$scope.changeColor = function(color){
$scope.color = color || "Red";
$scope.colorChanged();
};
Add ng-change="colorChanged()" to radio button:
<input type="radio" ng-model="$parent.color" ng-value="color" id="{{color}}" name="color" ng-change="colorChanged()">
Change the textbox to use other as the model. Use ng-focus to detect when textbox is focused and then set color to 'Other'. Doing this will select the radio button.
<input type="text" ng-model="$parent.other" ng-show="color=='Other'" ng-focus="$parent.color = 'Other'"/>
Update the display of the color to show the other text:
The chosen color is <strong>{{color}}<span ng-if="color === 'Other' && other != ''"> - {{other}}</span></strong>
Plunkr
I made some very small modifications to your pen HERE.
The short of it is, instead of having 'Other' as a value, i made it a blank option, with the input actually controlling the value.
$scope.colors = [
"Red",
"Green",
"Blue",
""
];
html:
<label >
{{color || 'Other'}}
</label>
<input type="text" ng-model="$parent.color" ng-show="color==''">
This allows the input to actually control the value of 'Other'...

Radio buttons plus a text field in Angular.js

Using AngularJS, I would like to create a list of options with radio buttons, the last of which has an empty text field labeled 'Other' for inputing an option that is not in the list. Here's a demonstration of what I have in mind that I bootstrapped in CodePen. Since Stack Overflow insists on including CodePen code in this message, here it is:
js:
angular.module('choices', [])
.controller("MainCtrl", ['$scope', function($scope) {
$scope.color = '';
$scope.colors = [
"Red",
"Green",
"Blue",
"Other"
];
$scope.changeColor = function(){
$scope.color = "Red"
};
}]);
html:
<html>
<head>
<body ng-app="choices" ng-controller="MainCtrl">
<div ng-repeat="color in colors">
<input type="radio" ng-model="$parent.color" ng-value="color" id="{{color}}" name="color">
<label>
{{color}}
</label>
<input type="text" ng-model="$parent.color" ng-show="color=='Other'">
</div>
<p></p>
The chosen color is <strong>{{color}}</strong>
<p></p>
<button ng-click="changeColor()">Change color</button>
</body>
</html>
Here is what I want this demo app to do:
When I choose any option except for Other, the text field should remain blank;
If I place cursor in the text field, the option Other should be selected
Once I start typing in the text field, the option Other should remain selected
If I change the model that registers the options (in the demo app achieved by clicking the Change color button), the corresponding radio button should be selected.
I achieved most of that functionality by using three models (one for color, one for keeping track of radio buttons and one for the Other field) and three watchers, but the resultant app seems brittle and fails some of the tests. Could you please suggest a better way for creating such a selector in Angular using as few models and watchers as possible?
(My question is somewhat similar to this SO question, but I hope is different enough not to be considered a duplicate.)
Add a separate scope property for the other text:
$scope.other = '';
Add a colorChanged() method which will be called when the color is changed. This will set the other text to empty if color is not 'Other':
$scope.colorChanged = function () {
if ($scope.color != 'Other') {
$scope.other = '';
}
};
This will also need to be called from changeColor(). I ended up changing changeColor to allow the color to be passed in. It otherwise defaults to red:
$scope.changeColor = function(color){
$scope.color = color || "Red";
$scope.colorChanged();
};
Add ng-change="colorChanged()" to radio button:
<input type="radio" ng-model="$parent.color" ng-value="color" id="{{color}}" name="color" ng-change="colorChanged()">
Change the textbox to use other as the model. Use ng-focus to detect when textbox is focused and then set color to 'Other'. Doing this will select the radio button.
<input type="text" ng-model="$parent.other" ng-show="color=='Other'" ng-focus="$parent.color = 'Other'"/>
Update the display of the color to show the other text:
The chosen color is <strong>{{color}}<span ng-if="color === 'Other' && other != ''"> - {{other}}</span></strong>
Plunkr
I made some very small modifications to your pen HERE.
The short of it is, instead of having 'Other' as a value, i made it a blank option, with the input actually controlling the value.
$scope.colors = [
"Red",
"Green",
"Blue",
""
];
html:
<label >
{{color || 'Other'}}
</label>
<input type="text" ng-model="$parent.color" ng-show="color==''">
This allows the input to actually control the value of 'Other'...

Retrieve all ngModels within a transcluded directive

i'm trying to retrieve all ngModels within a transcluded directive. Is this the right way or is there a simpler solution to find the child model values?
Is there also a selector where i can use queries like this one ("input", "textarea", "select", ...)
The sample: http://plnkr.co/edit/tjjBEa1I1fIISvGbRz7e?p=preview
I don't know if this is the right approach. All your models are inside your $scope so why don't getting it from there directly?
For changes you shouldn't use jQuery like element.on('change', ...) style, instead bind an event listener to the model with $scope.$watch('model', ...) that would be the angular way.
Are you trying to disable all the inputs and clear their values when the 'Disable' checkbox is ticked?
I would recommend adding the ng-disabled directive to your inputs and binding it to a property on your model.
You can easily clear the input values by moving them onto an object on your model and then clearing that property when the controls are disabled.
Updated version of your plunkr: http://plnkr.co/edit/xKRF3rfAB8EcSKEBEeKd?p=preview
Here is the updated code based on your example:
app.js:
app.controller('MainCtrl', function($scope) {
// 1. Bind the 'Disable' checkbox's ng-model to this value.
$scope.disabled = false;
// 2. Move all your model data down one level onto the 'viewData' object.
// Now we can change all the input values just by changing the `$scope.viewData` object.
$scope.viewData = {
user: {
lastname: 'Doe',
firstname: 'John'
},
checker: true,
opt: 'Item 2'
};
// 3. Add a change callback on the 'Disable' checkbox to call this function.
// Replace the $scope.viewData to change the input values.
var originalData = null;
$scope.disabledChanged = function() {
if ($scope.disabled) {
// Clear the previous object.
originalData = $scope.viewData;
$scope.viewData = null;
} else {
// Revert back to the previous object.
$scope.viewData = originalData;
}
}
})
index.html:
<fieldset id="f">
<legend>
<label><input type="checkbox" child-disable child-disable-root="f" ng-model="disabled" ng-change="disabledChanged()" /> Disable</label>
</legend>
<hr />
<p><input type="checkbox" ng-model="viewData.checker" ng-disabled="disabled" /> Test</p>
<p><input type="text" ng-model="viewData.user.firstname" ng-disabled="disabled" />
<input type="text" ng-model="viewData.user.lastname" ng-disabled="disabled" /></p>
<p><textarea ng-model="viewData.multi" ng-disabled="disabled"></textarea></p>
<div>
<select ng-model="viewData.opt" ng-disabled="disabled">
<option>Item 1</option>
<option>Item 2</option>
<option>Item 3</option>
</select>
</div>
<div>
<button>Click</button>
</div>
</fieldset>

Resources