<select> doesn't have a selected value - angularjs

I try to set the value of my select dynamically in the controller the following way:
angular.module('vocabApp.controllers', []).
controller('indexController', function ($scope, dictionaryHandler) {
$scope.expressions = [
{ expression: "", meanings: ["first", "second"], selected: "" }];
$scope.counter = 0;
$scope.add = function (expressionString, expressionObject) {
if (expressionString.length == 1) {
$scope.expressions.push({ expression: "", meanings: [""] });
}
dictionaryHandler.sendJsonpRequestToGetMeanings(expressionString, function (meaningsWeAcquired) {
alert("callback called!");
expressionObject.meanings = meaningsWeAcquired;
expressionObject.selected = expressionObject.meanings[0];
});
};
});
The odd thing is that the content of "meaningsWeAcquired" shows up in the select list, but there is no default selected value. Here's the html:
<select ng-init="option.selected = item.meanings[0]" ng-model="option.selected" ng-options="option as option for option in item.meanings"></select>
On page load the default value is "first", so I don't get why the same thing doesn't work when I set the object's "selected" field from the callback method.

I can see that you are setting expressionObject.selected in the sendJsonpRequestToGetMeanings callback, but in the HTML the select ng-model attribute is set to "option.selected", which does not point to the value you set before. I guess that the select element is wrapped by the ng-repeat directive and "item" references current expresssionObject.
So you should try changing:
ng-model="option.selected"
to
ng-model="item.selected"

Related

how to set default value after ng-options completed?

assume that this is my controller:
function MainController(BaseInformation, baseInformationConstants) {
var vm = this;
getGenders();
function getGenders() {
vm.genders = BaseInformation.list({headerId: baseInformationConstants.genderId});
}
}
and this select tag, that i want to set default value for it with ng-init, but it didn't worked:
<select ng-init="vm.user.genderId = {id: vm.genders[0].id}"
ng-model="vm.user.genderId"
ng-options="gender.id as gender.topic for gender in vm.genders track by gender.id">
</select>

scope variable not updating with ng-change - angularjs

Seems like a simple problem though but finding it hard to fix.
There is a pagination component, that has a button & a dropdown. User can go to a page by either clicking the button or selecting that page number in dropdown.
The problem is, when I select a value in the dropdown, nothing happens. Because the scope variable doesnt change from the previous one.
aspx:
<div data-ng-app="app" data-ng-controller="ReportsCtrl">
<div id="paging-top">
<div>
<ul>
<li>
<select data-ng-model="SelectedPage" data-ng-change="ShowSelectedPage();"
data-ng-options="num for num in PageNumbers track by num">
</select>
</li>
<li data-ng-click="ShowNextPage();">Next</li>
</ul>
</div>
</div>
app.js
var app = angular.module("app", ["ngRoute"]);
ReportsCtrl.js
app.controller("ReportsCtrl", ["$scope","ReportsFactory",function ($scope,ReportsFactory) {
init();
var init = function () {
$scope.ShowReport(1);
}
$scope.ShowReport = function (pageNumber) {
GetUserResponsesReport(pageNumber);
}
function GetUserResponsesReport(pageNumber) {
$scope.UserResponsesReport = [];
var promise = ReportsFactory.GetReport();
promise.then(function (success) {
if (success.data != null && success.data != '') {
$scope.UserResponsesReport = success.data;
BindPageNumbers(50, pageNumber);
}
});
}
function BindPageNumbers(totalRows, selectedPage) {
$scope.PageNumbers = [];
for (var i = 1; i <= 5 ; i++) {
$scope.PageNumbers.push(i);
}
$scope.SelectedPage = selectedPage;
}
$scope.ShowSelectedPage = function () {
alert($scope.SelectedPage);
$scope.ShowReport($scope.SelectedPage);
}
$scope.ShowNextPage = function () {
$scope.SelectedPage = $scope.SelectedPage + 1;
$scope.ShowReport($scope.SelectedPage);
}
}]);
Say, the selected value in dropdown is 1. When I select 2 in the dropdown, the alert shows1. When Next is clicked, the dropdown selection changes to 2 as expected. Now, when I select 1 in the dropdown, the alert shows 2.
Tried to make a fiddle, but do not know how to do with a promise - http://jsfiddle.net/bpq5wxex/2/
With your OP SelectedPage is just primitive variable.
With every angular directive new scope is get created.
So,SelectedPage is not update outside the ng-repeat scope after drop-down is changed i.e. in parent scope which is your controller.
In order to do this,use Object variable instead of primitive data types as it update the value by reference having same memory location.
Try to define SelectedPage object in controller in this way.
$scope.objSelectedPage = {SelectedPage:''};
in HTML
<select data-ng-model="objSelectedPage.SelectedPage" data-ng-change="ShowSelectedPage();"
In ShowSelectedPage
$scope.ShowSelectedPage = function () {
console.log($scope.objSelectedPage.SelectedPage);
$scope.ShowReport($scope.objSelectedPage.SelectedPage);
}

Directive is not updating the view with async data, using controllerAs and bindToController

I'm having some trouble getting a directive to update my view.
In my controller I set the intial values for the attributes of the <tiki-list> directive. Then after, 2 seconds, I'm updating vm.listObjectSelected to test its async behaviour.
However, the view is not reflecting the update.
Controller:
var listObject = [{"display":"display1", "value":"value1"}, {"display":"display2", "value":"value2"}, {"display":"display3", "value":"value3"}]
vm.listObject = listObject
vm.listObjectSelected = [{"display":"display1", "value":"value1"}]
$timeout(function(){
vm.listObjectSelected = [{"display":"display1", "value":"value1"}, {"display":"display3", "value":"value3"}]
}, 2000)
HTML
<tiki-list max="" type="multi" list="editController.listObject" selected="editController.listObjectSelected"></tiki-list>
Directive
(function(){
'use strict';
angular.module("tiki").directive("tikiList", tikiList)
function tikiList(helper){
var directive = {
restrict:"EA",
scope:{
list: "=", //the object to repeat over, this contains 2 array's
retunObject: "=", //the array that is outputted
selected: "=", //preselected values
max: "=", //maximum range, other elements are greyed out, starts at 0
title:"#title", //the title of this list
type:"#type", //[single, multi]
},
templateUrl:"js/directive/list.html",
link:link,
bindToController: true,
controllerAs:"vm",
controller:controller
}
return directive
function link(scope, el, attr, ctrl){
scope.vm.onClick = onClick
// preprocess the "list" if there is a "selected" attribute
// the "selected" attribute is an object that contains the selected items
// return a "selectedItems" array containing the indeces of matching display names
// add the .active property to the "list" object to the correct indeces
if(scope.vm.selected){
var selectedItems = helper.isItemInList(helper.createArrayFromProperty(scope.vm.selected, "display"), helper.createArrayFromProperty(scope.vm.list, "display"))
for(var i = 0; i < selectedItems.length; i++){
scope.vm.list[selectedItems[i]].active = true
}
}
// add the property .disabled to the "list" if there is a max attribute
// the property will be added to all indeces that exceed the max value
if(scope.vm.max){
for(var y = 0; y < scope.vm.list.length; y++){
if(y >= scope.vm.max){
scope.vm.list[y].disabled = true
}
}
}
function onClick(index){
// only allow items that are in range of the "max" attribute are allowed to be clicked
if(!scope.vm.max || index < scope.vm.max){
if(scope.vm.type === "single"){
angular.forEach(scope.vm.list, function(val, key){
scope.vm.list[key].active = false
})
scope.vm.list[index].active = true
}
if(scope.vm.type === "multi"){
scope.vm.list[index].active = !scope.vm.list[index].active
}
}
}
scope.vm.listing = scope.vm.list
}
}
controller.$inject = [];
function controller(){
}
})()
Directive template
<ul class="listOptions">
<li class="listOptions-title" ng-class="{'show':title}">{{vm.title}}</li>
<li ng-click="vm.onClick($index)" ng-class="{'active':list.active, 'disabled':list.disabled}" ng-repeat="list in vm.listing track by $index">{{list.display}}</li>
</ul>
I think it has something to do with controllerAs but I can't wrap my head around it.
thx,
I think the reason is that the Array is a reference type. When you change the data in service or at async step, the data point goes to a new location in memory, but the data in directive or controller doesn't change.
Instead of writing your function like this:
$timeout(function(){
vm.listObjectSelected = [{"display":"display1", "value":"value1"}, {"display":"display3", "value":"value3"}]
}, 2000)
You should try doing it this way:
$(timeout(function(){vm.listObjectSelected.push({you need data here})},200)
or you can use a promise ,you can return a promise and get it in directive ,use
promise.then(function(){//let data = service.data again}
Hope this can help you.

AngularJS - Changing a variable inside a controller method doesn't update the $scope variable

I want to create a method in my controller to set to null different variables from my controller $scope. So I've this in my controller :
FootCreator.controller('FooController', function($scope) {
$scope.zoo = {
id: 1,
name: 'Lorem',
};
$scope.foo = {
id: 2,
title: 'bar',
};
$scope.deleteProperty = function(property) {
property = null;
};
});
And in my HTML I call it this way (for example) :
<a ng-click="deleteProperty(zoo)" class="remove icon-remove" title="Remove"></a>
When I console.log() the $scope.zoo it's not set to null. I think I must do something bad but can't find what. I try to do that not to have a deleteZoo(), deleteFoo() etc.
Thanks for the help/tips !
In your deleteProperty method, you are just setting the property parameter to null and this is never going to have any effect on your scope.
A simplified example of what you're doing here is:
$scope.zoo = { id: 1, name: 'Lorem' };
var property = $scope.zoo;
property = null;
console.log($scope.zoo); // previous line had no effect on $scope.zoo
I would suggest passing the property name as a string instead of the property itself. Then you can do this:
$scope.deleteProperty = function(property) {
delete $scope[property];
};
<a ng-click="deleteProperty('zoo')" class="remove icon-remove"
title="Remove"></a>
If you really want to pass the property itself (like you're doing in your HTML), you'd need to loop through all the properties to find the one that matches:
$scope.deleteProperty = function(property) {
for (var p in $scope) {
if ($scope.hasOwnProperty(p) && $scope[p] === property) {
delete $scope[p];
}
}
};

AngularJS Select Not Binding To Ng-Model

My angular select isn't binding. I can tell the value is correct, but the select isn't updated. Why is not binding if the value is there?
<div ng-controller="MyController" ng-app>
<select class="form-control" ng-model="colorId"ng-options="color.id as color.name for color in colorList">
<option value="">--Select a Color--</option>
</select>
<input type="button" value="submit" ng-click="Select()"></input>
function MyController($scope) {
$scope.colorList = [{
id: '1',
name: 'red'
}, {
id: '2',
name: 'blue'
}, {
id: '3',
name: 'green'
}];
var colorId = 3;
$scope.colorId = colorId;
alert($scope.colorId);
$scope.Select = function () {
var colorId = 2;
$scope.colorId = colorId;
}
}
Here is a fiddle:
http://jsfiddle.net/ky5F4/23/
you need to change the id to a string when doing Select
$scope.Select = function () {
console.log('select fired');
var colorId = 1;
$scope.mySelection.colorId = colorId + "";
}
http://jsfiddle.net/bxkwfo0s/2/
next you should use a property of an object rather than just a scope variable, this will ensure proper model binding
ng-model="mySelection.colorId"
where the object could be something simple
$scope.mySelection = {colorId : colorId };
There are two errors with your code:
You are using colorList as your model in ng-options, but you are calling it datasets in your controller.
You use strings for the id, but set the $scope.colorId to a number.
Here is an updated fiddle changing ids to numbers and changing $scope.datasets to $scope.colorList
function MyController($scope) {
$scope.colorList = [{
id: 1,
name: 'red'
}, {
id: 2,
name: 'blue'
}, {
id: 3,
name: 'green'
}];
var colorId = 3;
$scope.colorId = colorId;
alert($scope.colorId);
$scope.Select = function () {
var colorId = 2;
$scope.colorId = colorId;
}
}
Consider making your ng-model be an object, specifically one of the objects that are already in your $scope.colorList. If you do that you should be able to avoid the post-processing you're doing in the click handler.
So your select will look like this:
<select class="form-control" ng-model="selectedColor"
ng-options="color.name for color in colorList"></select>
One gotcha is that if you have an object in your controller that looks JUST LIKE your red object, like$scope.selectedColorObj = { id : '1', name:'red' } and set the select's ng-model to that option, it won't work. Angular will see that you're setting to the ng-model to an object that's not actually in your data source and add an extra option with value="?", so I use $filter in this case to grab the matching member of the array:
$scope.colorId = '3';
$scope.selectedColor = $filter('filter')( $scope.colorList,{ id: $scope.colorId})[0];
See http://jsfiddle.net/ky5F4/92/

Resources