Get selected object in angular select - angularjs

I have a select that I'm populated and defaulting based on an outside value:
<select ng-model="course.instructor_id" ng-options="instructor.id as instructor.first_name for instructor in instructors"></select>
I think I need to keep the ng-model and options pretty close to this so it updates/defaults the course model correctly but I need to grab a property of the currently selected instructor object.
How do I get the currently selected object for this select?
I want to be able to show the picture of the currently selected instructor:
<img ng-src="selected_instructor.picture""/>

If you need to update the course model when a new instructor is selected, you can use
$scope.$watch
to watch for changes of the selected_instructor value.
Here is an example:
app.controller("instructorCtrl", function($scope) {
$scope.course = {
instructor_id: null
};
$scope.instructors = [{
id: 1,
firstName: "Stefano",
lastName: "Baroni",
imageUrl: "http://placehold.it/300x150"
}, {
id: 2,
firstName: "Elisa",
lastName: "Molinari",
imageUrl: "http://placehold.it/150x150"
}, {
id: 3,
firstName: "Stefano",
lastName: "De Gironcoli",
imageUrl: "http://placehold.it/200x150"
}]
$scope.$watch(
"selected_instructor",
function(newValue, oldValue) {
if (newValue === oldValue) {
return;
}
$scope.course.instructor_id = newValue.id;
}
)
})
html template:
<div ng-controller="instructorCtrl">
<img src="{{selected_instructor.imageUrl}}" />
<br/>
<select ng-model="selected_instructor" , ng-options="instructor.lastName for instructor in instructors">
<option value="">-- choose instructor--</option>
</select>
<br/><label>Currently selected instructor:</label>{{selected_instructor}}
<br/><label>Course:</label> {{ course }}
</div>

From what I've seen of your question, you are never setting the selected_instructor. Here's a Fiddle of my solution for you.
You were basically correct in your select tag and its ng-directives. Here's what I used for the HTML template:
<div ng-app="demoApp" ng-controller="demoCtrl">
<select ng-model="instructor" ng-options="teacher.lastName for teacher in instructors">
{{teacher.lastName}}
</select>
<img src="{{instructor.imageUrl}}" />
</div>
For the Angular base, I made a dummy app and controller as such:
angular.module('demoApp', []);
angular.module('demoApp')
.controller('demoCtrl', function ($scope) {
$scope.instructor = null;
$scope.instructors = {
{
firstName: "Scott",
lastName: "Bohle",
courses: ["CHEM110", "CHEM222"],
imageUrl: "http://placehold.it/300x150"
},
{
firstName: "Arial",
lastName: "Fenster",
courses: ["CHEM180"],
imageUrl: "http://placehold.it/150x150"
}
}
});
Also, bonus points to anyone who can tell what University I went to... (Hint, it's the best in Canada.)

Related

AngularJS two-way data binding not working properly in directive

i am trying to implement radio-button list using ng-repeat.
typeList.html
<div ng-repeat="type in types" >
<input type="radio" id={{type.id}} name="{{type.name}}" ng-model="result" ng-value="type.id" >
{{type.name}}
<div> Result {{result}} </div> //result is changing only in the row of clicked radio-button. It should change in every row.(two way data-binding).
</div>
Directive:
angular.module('app').directive('myList',function(){
return{
restrict: 'A',
scope: {
types: '=', //here list is passed to be printed with ng-repeat
result: '=' //here I want to store which radio-button was selected last time by id
},
templateUrl: 'html/typeList.html'
};
});
Directive has isolated scope. I am passing two parameters. List to be printed with radio buttons and result object which stores answer(id-what radio button was clicked last time) in parent scope. Unfortunately whenever i click on radio-buttons my result is changing only locally.
Passing parameters to my directive.
<div my-list types="list" result="selected"></div>
Passed list and result paramater from controller to myList directive.
$scope.list = [
{ id: 1, name:'Name 1' },
{ id: 2, name:'Name 2' },
{ id: 3, name:'Name 3' }
];
$scope.selected = -1;
I would be grateful for any help.
You have to pass a non-primitive object to the model to get its reference for two-war binding. Just wrap selected into an object for its reference.
In your controller use.
$scope.list = [{
id: 1,
name: 'Name 1'
}, {
id: 2,
name: 'Name 2'
}, {
id: 3,
name: 'Name 3'
}];
$scope.ctrlModel = {
selected: -1
}
And in the Markup that is 'html/typeList.html'
<div ng-repeat="type in types" >
<input type="radio" id={{type.id}} ng-model="result.selected" ng-value="type.id" >
{{type.name}}
</div>
Result {{result.selected}}
Working Fiddle Demo
Hope it helps.
try to have scope variables as object like
$scope.types = {
list: {},
selected: 'radioValueThatNeedsToBeSelected'
}

Angular Radio Buttons Instead of Select

I'm trying to replace a select with radio buttons - but when I swap to radio buttons I loose my initial selection and the selecting breaks.
$scope.selection = Address.get(); // { id: 1, name: "Home" };
$scope.addresses = Address.query(); // [{ id: 1, name: "Home" }, { id: 2, name: "Work" }];
From (in this sample the select has "Home" selected):
<select class="form-control" ng-model="selection"
ng-options="address.street for address in addresses track by address.id">
</select>
To (in this sample the radio button for "Home" is not selected):
<div ng-repeat="address in addresses track by address.id">
<label>
<input type="radio" ng-value="address" ng-model="selection" />
<span>{{address.name}}</span>
</label>
</div>
Fiddle: https://jsfiddle.net/xczdcqx0/7/
EDIT:
I need the selection to reflect the id and name after changes:
<span>Selection:</span> <span>{{selection.name}} - {{selection.id}}</span>
Try this instead (for you radio input). Turns out that the ng-repeat is what's throwing it off (you needed to use $parent.selection):
<input type="radio" ng-value="address" ng-model="$parent.selection"/>
I think it's working the way you'd hope with this update to your fiddle
Initial Value
Jeez. I feel like an idiot, but I finally figured out that angular has no way of telling that your initial "selection" is the same as address[0].
So - I had to change the way you set $scope.selection as well:
app.controller("SampleController", ['$scope', function($scope) {
$scope.addresses = [
{ id: 1, name: "Home" },
{ id: 2, name: "Work" },
];
$scope.selection = $scope.addresses[0];
}]);
Now we're all set. Sheesh ... that was one of those "hiding in plain sight" bugs...
The value and model should be a string according to the input[radio] docs:
<input type="radio" ng-value="address.name" ng-model="selection.name" />
JSFiddle Demo: **https://jsfiddle.net/xczdcqx0/2/
Source:
<div ng-repeat="address in addresses track by address.id">
<label>
<input type="radio" ng-checked="checked(address)" ng-click="click(address)" />
<span>{{address.name}}</span>
</label>
</div>
Controller:
app.controller("SampleController", ["$scope", "Address", function($scope, Address) {
$scope.selection = Address.get(); // { id: 1, name: "Home" };
$scope.addresses = Address.query(); // [{ id: 1, name: "Home" }, { id: 2, name: "Work" }];
$scope.checked = function(address) {
return address.id === $scope.selection.id;
};
$scope.click = function(address) {
$scope.selection = address;
};
}]);
Note: extracted partially from solutions provided by #bri.

Selecting a default value on select box options with AngularJS

I have read several posts on this issue and the solutions given on this site don't seem to work for me. I have a select box with several options and I need a default value to be show to the user. Currently no option is selected. What could be wrong with this code.
HTML
<select class="form-control input-sm" name="collegeTranscripts1" id="collegeTranscripts1" data-ng- model='transcriptCAdata.typeAccepted' data-ng-options='option.value as option.name for option in typeOptions1'></select>
JS
$scope.typeOptions1 = [
{ name: 'Please Select', value: 'selected' },
{ name: 'Official', value: 'OFFICIAL' },
{ name: 'Unofficial', value: 'UNOFFICIAL' },
{ name: 'None', value: 'NONE' }
];
$scope.form = {type : $scope.typeOptions1[0].value};
There are a couple of problems that I see in your code:
The HTML attribute data-ng-model is separated, it looks like this: data-ng- model='transcriptCAdata.typeAccepted'.
Another is that in your model, you are using a scope attribute transcriptCAdata.typeAccepted but you didn't declare it in your controller. What I see in your controller though is $scope.form = {type : $scope.typeOptions1[0].value};.
You simply have to change your data-ng-model to data-ng-model="form.type".
DEMO
angular.module('app', [])
.controller('Ctrl', function($scope) {
$scope.typeOptions1 = [
{ name: 'Please Select', value: 'selected' },
{ name: 'Official', value: 'OFFICIAL' },
{ name: 'Unofficial', value: 'UNOFFICIAL' },
{ name: 'None', value: 'NONE' }
];
$scope.form = {type : $scope.typeOptions1[1].value};
});
<div ng-app="app" ng-controller="Ctrl">
<select class="form-control input-sm" name="collegeTranscripts1"
id="collegeTranscripts1" data-ng-model='form.type'
data-ng-options='option.value as option.name for option in typeOptions1'>
</select>
{{form.type}}
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
UPDATE:
I have copied the PLUNKER you have provided and revised it, since it had problems in it.

Saving a checkbox list in Angularjs with node

I want to save and load a checkbox list using binding in angularjs with a node backend. This SO question (How do I bind to list of checkbox values with AngularJS?) answers how I can load the check box from a static javascript object but how can I save the checkbox values after the user selects them?
I want to save the checkbox values in a single field but how can I tell angular to bind the checkbox values into a single field defined in a model to my mongodb? I cant just use ng-model as there are multiple checkboxes.
Needless to say that I am new to angular so any help here is greatly appreciated ...
Thanks for any help you can provide.
kseudo
Just add ng-model to your checkbox. By this way you can update model in controller on any checkbox state change.
Here is example:
HTML
<div ng-controller="Ctrl">
<label ng-repeat="fruit in fruits">
<input
type="checkbox"
name="fruit.name"
ng-model="fruit.value"
> {{fruit.name}}
</label>
<pre>{{fruits| json}}</pre>
</div>
JS
var app = angular.module('app', []);
function Ctrl($scope) {
$scope.fruits = [{
name: 'apple',
value: false
}, {
name: 'orange',
value: false
}, {
name: 'pear',
value: false
}, {
name: 'naartjie',
value: false
}];
}
Demo Fiddle
[EDIT]
BTW we can make the copy by using angular.copy() method. When we press button, the new copy of fruits model will be created (and you should send it to server as json). Old model fruits will stay the same:
$scope.fruitsCopy = [];
$scope.init = function(){
$scope.fruitsCopy = angular.copy($scope.fruits );
}
To convert data to JSon I would use:
var jsonData = JSON.stringify($scope.fruitsCopy);
Demo2 Fiddle
Let's say you defined your model as such:
function Ctrl($scope) {
$scope.items = [{
name: 'A',
checked: false
}, {
name: 'B',
checked: false
}, {
name: 'C',
checked: false
}, {
name: 'D',
checked: false
}];
}
And created a view for the model:
<ul>
<li ng-repeat="item in items">
<label>
<input type="checkbox" ng-model="item.checked">
{{item.name}}
</label>
</li>
</ul>
<button ng-click="save()">save</button>
Next you have to define save function:
$scope.save = function() {
//angular.toJson converts array to string, something like
// '[{"name":"A","checked":false},{"name":"B","checked":true},...]'
var json = angular.toJson($scope.items);
//Service is angular service for your model that makes http requests to your backend
Service.save(json).then(function(){
//here you can notify user that data is persisted
}, function() {
//here you can notify user that there was a problem with request
});
}
And a simple model service:
.service('Service', function($http) {
return new function() {
this.save = function(data) {
return $http.post('url/to/backend', data);
}
}
});

AngularJS - Is there an easy way to set a variable on "sibling" scopes?

I have this problem where I am trying to make a click on a div hide all the other divs of the same "kind". Basically I'd have to, from a child scope set the variable on all other "sibling" scopes.
To illustrate this, I have created the following:
HTML
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<div ng-repeat="model in models" ng-controller="MyChildCtrl">
<a ng-click="toggleVisibility()">toggle {{ model.name }} {{ visibility }}</a>
<div ng-show="visibility">
{{ model.name }}
</div>
</div>
</div>
</div>​
JavaScript
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
console.debug('scope');
$scope.models = [
{ name: 'Felipe', age: 30 },
{ name: 'Fernanda', age: 28 },
{ name: 'Anderson', age: 18 }
];
}
function MyChildCtrl($scope) {
$scope.visibility = false;
$scope.toggleVisibility = function() {
$scope.visibility = !$scope.visibility;
}
}
JSFiddle: http://jsfiddle.net/fcoury/sxAxh/4/
I'd like that, every time I show one of the divs, that all other divs would close, except the clicked one.
Any ideas?
#kolrie while your approach works I would suggest a different solution which doesn't require any changes to the model. The basic idea is to keep a reference to a selected item and calculate viability by comparing a current item (inside ng-repeat) with a selected one.
Using this solution the toggle function would become:
$scope.toggleVisibility = function(model) {
$scope.selected = model;
};
and calculating visibility is as simple as:
$scope.isVisible = function(model) {
return $scope.selected === model;
};
Finally the relevant part of the markup is to be modified as follows:
<div ng-controller="MyCtrl">
<div ng-repeat="model in models">
<a ng-click="toggleVisibility(model)">toggle {{ model.name }} {{ isVisible(model) }}</a>
<div ng-show="isVisible(model)">
{{ model.name }}
</div>
</div>
</div>
Here is a complete jsFiddle: http://jsfiddle.net/XfsPp/
In this solution you can keep your model untouched (important if you want to persist it back easily) and have AngularJS do all the heavy-lifting.
OK, I have added a visible attribute to the model, and I managed to get this done:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
console.debug('scope');
$scope.models = [
{ name: 'Felipe', age: 30, visible: false },
{ name: 'Fernanda', age: 28, visible: false },
{ name: 'Anderson', age: 18, visible: false }
];
}
function MyChildCtrl($scope) {
$scope.toggleVisibility = function() {
angular.forEach($scope.models, function(model) {
model.visible = false;
});
$scope.model.visible = true;
}
}
Live here: http://jsfiddle.net/fcoury/sxAxh/5/
Is this the most efficient way? Do you think it's a good practice if I inject this visible attribute into my model data after getting it via AJAX?

Resources