<select> getter-setter receives object parameter as string - javascript

Why is that moo object parameter comes as [object Object] string?
var App = angular.module('myApp', [
'controllers']);
var ctrls = angular.module('controllers', []);
ctrls.controller('myController', ['$scope', function ($scope) {
$scope.moos = [
{'id':1, 'name': 'foo'}, {'id':2, 'name': 'boo'}
];
$scope.proxy = {
setter: function (moo) {
if(!arguments.length) return;
console.log(moo);
$scope.moo = moo;
}
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.5/angular.js"></script>
<div ng-app="myApp" ng-controller="myController">
<p>{{moo.name}}</p>
<select ng-model="proxy.setter" ng-model-options="{ getterSetter: true }">
<option ng-selected="moo.id===m.id" ng-value="m" ng-repeat="m in moos">{{m.name}}</option>
</select>
</div>

ng-value will put a string into the value of the option. And a javascript object converted into a string is [object Object].
But you can put m.id in your ng-value to retrieves it in your javascript code. Here an example :
var App = angular.module('myApp', [
'controllers']);
var ctrls = angular.module('controllers', []);
ctrls.controller('myController', ['$scope', function ($scope) {
$scope.moos = [
{'id':1, 'name': 'foo'}, {'id':2, 'name': 'boo'}
];
$scope.proxy = {
setter: function (id) {
if(!arguments.length) return;
var moo = $scope.moos.filter(function(moo) {
return moo.id == id;
})[0];
console.log(moo);
$scope.moo = moo;
}
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.5/angular.js"></script>
<div ng-app="myApp" ng-controller="myController">
<p>{{moo.name}}</p>
<select ng-model="proxy.setter" ng-model-options="{ getterSetter: true }">
<option ng-selected="moo.id===m.id" ng-value="m.id" ng-repeat="m in moos">{{m.name}}</option>
</select>
</div>

Related

How to get checked values from checkbox using Angular JS

Am new to angular JS. I have following check box and the data is coming from web service:
<label ng-repeat="r in MedicalConditions track by $index">
<input ng-model="ids[$index]" type="checkbox" ng-checked="r.value">
{{r.conditions_name}}
</label>
In console.log value is perfectly right as per my requirements. How to push value to an array i.e., arr[] and stringify it. I tried code like this..
//To fetch Medical Conditions List
$scope.parameter = "{}";
$scope.class0 = "{}";
$http.get('http://192.168.1.129:8080/apartment//member/medical/conditions/list').then(function(response) {
$scope.MedicalConditions = response.data.list;
});
$scope.$watchCollection('ids', function(newVal) {
$scope.parameter.class0 = $scope.ids;
});
$scope.alertdata = function() {
var parameter = {
"first_name": $scope.first_name,
"role": [{
"role_id": 1,
"name": "Admin",
"details": "text"
}],
"associated": [{
"associated_id": 1,
"associated_name": "Parent",
"primary_member_id": 1
}],
"class0": $scope.ids
}
parameter = JSON.stringify(parameter);
May be this will help:
angular.module('app', [])
.controller('Controller', function($scope) {
$scope.ids = {};
$scope.arr = {};
$scope.MedicalConditions = {};
$scope.MedicalConditions[0] = {};
$scope.MedicalConditions[0].value= true;
$scope.MedicalConditions[0].conditions_name= 'first value';
$scope.MedicalConditions[1] = {};
$scope.MedicalConditions[1].value= false;
$scope.MedicalConditions[1].conditions_name= 'seconde value';
$scope.$watchCollection('ids', function(newVal) {
$scope.parameter.class0 = $scope.ids;
});
$scope.parameter = {};
$scope.parameter.firstname = 'dummy name';
$scope.parameter.class0 = $scope.ids;
});
<!DOCTYPE html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="app">
<div ng-controller="Controller">
<label ng-repeat="r in MedicalConditions track by $index">
<input ng-model="ids[$index]" type="checkbox" ng-checked="r.value" > {{ r.conditions_name}}
</label>
<br>
Parameter: {{parameter}}
</div>
</body>
</html>
Try like below...
var app = angular.module('exApp',[]);
app.controller('ctrl', function($scope){
$scope.ids = [];
$scope.arr = [];
$scope.checkSelected = [];
$scope.MedicalConditions = [{"conditions_name":"xxz","conditions_id":"1"}, {"conditions_name":"yyz","conditions_id":"2"}, {"conditions_name":"zzz","conditions_id":"3"}];
$scope.$watchCollection('ids', function(newVal) {
for (var i = 0; i < newVal.length; ++i) {
console.log(newVal[i]);
$scope.arr.push(newVal[i]);
}
});
$scope.checkAllR = function () {
$scope.checkAll = !$scope.checkAll;
if ($scope.checkAll) {
$scope.checkSelected = [];
angular.forEach($scope.MedicalConditions, function (checkR) {
checkR.check = $scope.checkAll;
$scope.checkSelected.push(checkR);
});
}
else {
$scope.checkSelected = [];
angular.forEach($scope.MedicalConditions, function (checkR) {
var idx = $scope.checkSelected.indexOf(checkR);
checkR.check = $scope.checkAll;
$scope.checkSelected.splice(idx, 1);
});
}
};
$scope.addChecked = function (checked) {
if ($scope.checkSelected == undefined || $scope.checkSelected == null) {
$scope.checkSelected = [];
}
var idx = $scope.checkSelected.indexOf(checked);
// delete if exists
if (idx > -1) {
$scope.checkSelected.splice(idx, 1);
checked.check = false;
}
// add
else {
$scope.checkSelected.push(checked);
checked.check = true;
}
$scope.checkAll = $scope.checkSelected.length == $scope.MedicalConditions.length ? true : false;
};
var parameter = {
"first_name": $scope.first_name,
"middle_name": $scope.middle_name,
//"class0": /*stringified data i.e., arr[] */
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app="exApp" ng-controller="ctrl">
Select All : <input type="checkbox" name="checkbox" value="1" ng-checked="checkAll" ng-click="checkAllR()"><br>
<label ng-repeat="r in MedicalConditions">
<input type="checkbox" name="checkbox" class="check-nolabel" value="1" ng-checked="r.check" ng-click="addChecked(r)"> {{ r.conditions_name}}
</label><br><br>
{{checkSelected}}
</body>
Hope this helps.
<div ng-app="myApp" ng-controller="MyCtrl">
<label ng-repeat="r in MedicalConditions track by $index">
<input ng-model="ids[$index]"
ng-init="ids[$index] = r.value"
type="checkbox">
{{r.condition}}
</label>
</div>
And here is your controller.
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope){
$scope.ids = [];
$scope.MedicalConditions = [{
_id: 1,
value: true,
condition: 'Condition 1'
}, {
_id: 2,
value: false,
condition: 'Condition 2'
}, {
_id: 3,
value: true,
condition: 'Condition 3'
}];
});
JsFiddle
<label ng-repeat="r in MedicalConditions track by $index">
<input ng-model="ids[$index]" type="checkbox" ng-change="valCh(r)"> {{r.conditions_name}}
</label>
Controller code will look like this :
var postApp = angular.module('EntityApp', []);
postApp.controller('EntityAppCntroller', function($scope, $http, $window, $timeout, $location) {
//To fetch Medical Conditions List
$http.get('http://111.222.444:8080/apartment//member/medical/conditions/list').then(function(response) {
$scope.MedicalConditions = response.data.list;
});
var list = [];
$scope.valCh = function(value) {
list.push(value);
JSON.stringify(list);
}
$scope.alertdata = function() {
var parameter;
parameter = {
"parameter": {
"first_name": $scope.first_name,
"medicalconditions": list
}
}
$http({
url: 'http://111.222.333:8080/apartment//save/member/details',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify(parameter)
}).success(function(data, status) {
if (data.status == 'success') {
alert("User Created");
$location.reload();
} else if (data.status == 'failure') {
alert("Some failure please try again later !!!");
}
});
};
});

Using ng-change to populate one dropdown based on the selection of another in AngularJS

Ok, A keyword will be selected from the first dropdown and based on that a second dropdown with "Qualifiers" will be populated.I cant get anything to populate in the qualifier dropdown how will I be able to pass the keyword to the service? or am I already doing that with ng-change="getQualifier(keyword)" but I may need to modify the service to take in a parameter right?
this is my angular controller that handles these too dropdowns
var StockItemMultiMillInquiryController = function ($scope, $sce, $rootScope, $modal, $window, StockItemMultiMillService, QualifierService, KeywordService) {
$rootScope.title = 'Stock Item Multi Mill Inquiry';
$scope.allMills = [];
$scope.mill = '';
$scope.stockNumber = '';
$scope.description = '';
$scope.qtyonhand = '';
$scope.qualifier = '';
$scope.costType = '';
$scope.keyword = '';
$scope.allKeywords = [];
$scope.qualifier = '';
$scope.selectedQualifier = '';
$scope.allQualifiers = [];
KeywordService.getKeyword().then(function (keywords) {
$scope.allKeywords = keywords
});
$scope.getQualifiers(keyword)
{
QualifierService.getQualifier(keyword).then(function(qualifiers) {
$scope.allQualifiers = qualifiers
});
}
the services this is using
app.service('QualifierService', function ($http, cache) {
return {
getQualifier: function () {
var qualifiers = cache.get('qualifier');
if (!qualifiers) {
return $http({ method: 'JSONP', url: "/api/core/qualfier/qualifier?callback=JSON_CALLBACK", params: {} }).then(function (result) {
if (result.data.success) {
cache.put('qualifier', result.data.data);
return result.data.data;
} else {
return [];
}
});
} else {
var deferred = $q.defer();
deferred.resolve(qualifiers);
return deferred.promise;
}
}
};
});
the htm page
<select class="btn btn-info dropdown-toggle" style="width: 92%" ng-model="keyword" ng-change="getQualifier(keyword)">
<option value="">Select a Keyword</option>
<option ng-repeat="keyword in allKeywords" value="{{keyword.description}}"> {{keyword.description}} </option>
</select><br/><br/>
<select class="btn btn-info dropdown-toggle" style="width: 92%" ng-model="selectedQualifier">
<option value="">Select a Qualifier</option>
<option ng-repeat="qualifier in allQualifiers" value="{{qualifier.description}}"> {{qualifier.description}} </option>
</select>
.Net Controller that the service calls
Function Qualifier(callback As String, keyword As String) As ActionResult
Dim res As New PCA.Core.Web.JSON.Response
Dim qualifierList As New List(Of ViewModels.Core.Qualifier)
For Each u As Trident.Core.Core.Qualifier In Trident.Core.Globals.TridentApp.ApplicationCache.Keywords.Qualifiers(keyword)
qualifierList.Add(New ViewModels.Core.Qualifier(u))
Next
Try
res.success = True
res.message = ""
res.data = qualifierList.OrderBy(Function(c) c.description)
Return New PCA.Core.Web.JSON.JSONPResult() With { _
.Data = res,
.Callback = callback
}
Catch ex As Exception
res.success = False
res.message = ex.Message
res.data = ""
Return New PCA.Core.Web.JSON.JSONPResult() With { _
.Data = res,
.Callback = callback
}
End Try
End Function
put ng-change on your first dropdown as its triggered when the value of the select element is changed, not the data.
Here's a simple working example:
index.html
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
<script src="ctrl.js"></script>
</head>
<body>
<div ng-app="app" ng-controller="moviesCtrl">
<h1>Movies By My Favorite Directors</h1>
<select ng-model="director">
<option ng-repeat="director in directors" value="{{ director.id }}">{{ director.name }}</option>
</select>
<select ng-model="film">
<option ng-repeat="film in movies[director].films" value="{{ film.id }}">{{ film.title }} starring {{ film.lead }}</option>
</select>
</div>
</body>
</html>
ctrl.js
angular.module('app', []).controller('moviesCtrl', function($scope) {
$scope.directors = [
{
id: 0,
name: "Stanley Kubrick"
},
{
id: 1,
name: "Quentin Tarantino"
}
];
$scope.movies = [
{
directorId: 0,
films: [
{
id: 0,
title: "The Shining",
lead: "Jack Nicholson"
},
{
id: 1,
title: "A Clockwork Orange",
lead: "Malcolm McDowell"
},
{
id: 2,
title: "2001: A Space Odyssey",
lead: "Keir Dullea"
}
]
},
{
directorId: 1,
films: [
{
id: 3,
title: "Pulp Fiction",
lead: "John Travolta"
},
{
id: 4,
title: "Inglorious Buddies",
lead: "Brad Pitt"
},
{
id: 5,
title: "Django Unchained",
lead: "Jamie Foxx"
}
]
},
];
});
For some reason this would not work in a jsFiddle, but it works in Chrome.

how to create a parent child list using angular

i am beginner in angular and i have a dynamic list like this
{.name:superParent,id:0,parrentId:null}
{.name:a,id:1,parrentId:0}
{.name:b,id:2,parrentId:0}
{.name:c,id:3,parrentId:1}
{.name:e,id:4,parrentId:3}
{.name:d,id:5,parrentId:2}
how can i implement it as nested list using angular and Recursive template? and also i want to keep each item-id in it self in the some attribute or property
i create this , but it dose not show the tree ,i can see the data only when i use ng-repeat in li
<ul>
<li ng-repeat="col in tree">{{col.Name}}</li>
</ul>
</div>
</div>
<script>
var app = angular.module('APP', []);
app.controller('IndexCtrl', function ($scope, $http) {
$scope.tree = [];
$scope.getList = function () {
//get data from server
$http.get("/person/GetTree")
.then(function (data) {
console.log("data:", data);
$scope.tree = data.data;
$scope.loading = false;
} )
}
$scope.getList();
});
app.directive('treeView', ['$compile', function($compile) {
return {
priority : 0,
restrict : "E",
replace : true,
scope : {
head: "=head",
children: "=children"
},
template: '<div><h4 id="{{head.id}}" ng-show="head.id>0">{{head.Name}}</h4> <ul> <li ng-repeat="item in items"> <tree-view head="item" children="children"></tree-view> </li> </ul></div>',
controller : ['$scope', function ($scope) {
var array = $scope.children;
var head = $scope.head;
//I used plugin linq.js
$scope.items = array.filter(function(val){
return val.parrentId==head.id;
});
}],
compile : function compile(element) {
var contents = element.contents().remove();
var contentsLinker;
return function (scope, iElement) {
if (angular.isUndefined(contentsLinker)) {
contentsLinker = $compile(contents);
}
contentsLinker(scope, function (clonedElement) {
iElement.append(clonedElement);
});
};
}
};
}]);
You can see example.
First I added main head item into your collection (it will be super parent for all other items):
{ name: "superparent", id: 0, parentId: null }
Then your collection will be looks like this:
tree = [
{name:'superparent',id:0,parrentId:Null},
{name:'a',id:1,parrentId:0},
{name:'b',id:2,parrentId:0},
{name:'c',id:3,parrentId:1},
{name:'e',id:4,parrentId:3},
{name:'d',id:5,parrentId:2},
];
All what we can do - create recursive directive (treeView) with such html template:
<div>
<h4 id="{{head.id}}" ng-show="head.id>0">{{head.name}}</h4>
<ul>
<li ng-repeat="item in items">
<tree-view head="item" children="children"></tree-view>
</li>
</ul>
</div>
I used TypeScript, but I sure you will easily undestand this code (d.compile function was taken from this answer):
module Directives {
export interface TreeItem {
name: string;
parrentId?: number
id: number;
}
TreeView.$inject = ['$compile'];
export function TreeView($compile): ng.IDirective {
var d: ng.IDirective = {};
d.priority = 0;
d.restrict = "E";
d.replace = true;
d.scope = {
head: "=head",
children: "=children"
};
d.templateUrl = '/somepath/treeView.html';
d.controller = ['$scope', function ($scope) {
var array: Array<TreeItem> = $scope.children;
var head: TreeItem = $scope.head;
$scope.items = array.filter(function(val){
return val.parrentId==head.id;
});
}];
d.compile = function compile(element) {
var contents = element.contents().remove();
var contentsLinker;
return function (scope, iElement) {
if (angular.isUndefined(contentsLinker)) {
contentsLinker = $compile(contents);
}
contentsLinker(scope, function (clonedElement) {
iElement.append(clonedElement);
});
};
};
return d;
}
}
At the end, into your html page, directive will be inserted this way, where tree[0] as you guessed is super parent:
<tree-view head="tree[0]" children="tree" ng-if="tree"></tree-view>

Is there a way in angularjs to dynamically set ngModel?

I have a component (a directive with isolate scope) that maps a list of objects to a list of inputs that allow to modify one property of that objects.
But I want to make that component universal.
So it should accept path to deeply nested property of each object in a list that should be bound to input.
For example we have a list of people, each of those have name spoken in different languages:
var people = [
{
age: 31,
multilang_attributes: {
en: {name: 'John'},
ru: {name: 'Иван'}
}
},
{
age: 29,
multilang_attributes: {
en: {name: 'Peter'},
ru: {name: 'Пётр'}
}
},
];
I want to apply my universal component to that list of people like the following:
<input-list
items="people",
item-model="multilang_attributes[locale].name"
></input-list>
I tried to create scope property with & that would allow me to execute expression in parent scope and then pass that expression to ngModel, but that does not work. You can look at this attempt in plunkr.
How that task can be approached in angular?
One option would be to $parse the accessor-string and use a getter/setter for the model. For this:
change the directive-html to:
item-accessor="'multilang_attributes.' + app.locale + '.name'"
This will make something like multilang_attributes.en.name available.
change the directive-code to:
app.directive('inputList', function () {
return {
restrict: 'E',
scope: {
items: '=',
itemAccessor: '='
},
template: '<ul><li ng-repeat="item in items"><input ng-model="getModel(item)" ng-model-options="{ getterSetter: true }" /></li></ul>',
controller: function ($scope, $parse) {
$scope.getModel = function(item) {
return function (newValue) {
var getter = $parse($scope.itemAccessor);
if (arguments.length > 0) {
getter.assign(item, newValue);
}
return getter(item);
};
};
}
};
});
External demo: http://plnkr.co/edit/VzFrBxNcsA5BarIVr6oG?p=preview
var app = angular.module('TestApp', [])
app.controller('AppCtrl', function AppController() {
this.locales = ['en', 'fr']
this.locale = 'en';
this.people = [
{
age: 31,
multilang_attributes: {
en: {name: 'John (en)'},
fr: {name: 'John (fr)'}
}
},
{
age: 29,
multilang_attributes: {
en: {name: 'Fred (en)'},
fr: {name: 'Fred (fr)'}
}
},
];
});
app.directive('inputList', function () {
return {
restrict: 'E',
scope: {
items: '=',
itemAccessor: '='
},
template: '<ul><li ng-repeat="item in items"><input ng-model="getModel(item)" ng-model-options="{ getterSetter: true }" /></li></ul>',
controller: function ($scope, $parse) {
$scope.getModel = function(item) {
return function (newValue) {
var getter = $parse($scope.itemAccessor);
if (arguments.length > 0) {
getter.assign(item, newValue);
}
return getter(item);
};
};
}
};
});
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.4.7" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" integrity="sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==" crossorigin="anonymous">
</head>
<body ng-app="TestApp" ng-controller="AppCtrl as app">
<div class="container">
<select ng-model="app.locale" ng-options="v as v for v in app.locales"></select>
<hr>
<input-list
items="app.people"
item-accessor="'multilang_attributes.' + app.locale + '.name'"
></input-list>
<hr>
<pre>{{ app.people|json }}</pre>
</div>
</body>
</html>
note that you should propably use proper injection-syntax and controllerAs/bindToController.

Angular Simple filter on ng-Repeat (>5)

I have a simple Angular form, where I'd like to filter the ng-repeat so that only values>5 are shown.
<body ng-controller="MainCtrl">
<div ng-repeat="item in items | filter:value:>5??????/p>
<p><input type=text ng-model="item.value"></p>
</div>
</body>
I can't determine the syntax for this. I am assuming it's a built in filter.
Reference:
app.controller('MainCtrl', function($scope) {
$scope.items = [ { value: 1 }, { value: 2 }, { value: 5}, { value: 7 } ];
There is no filter built in for this, nor is there any syntax you can pass to the default filter.
You can either:
1. Pass a function to the default filter.
HTML:
<div ng-repeat="item in items | filter:filterFn">
JS:
$scope.filterFn = function(item) {
return item.value > 5;
};
2. Register your own filter
HTML:
<div ng-repeat="item in items | greaterThan:5">
JS:
app.filter('greaterThan', function() {
return function(items, value) {
var filtered = [];
for (var i = 0; i < items.length; i++) {
if (items[i].value > value) filtered.push(items[i]);
}
return filtered;
}
});

Categories