Is there a way in AngularJS call function in select? - angularjs

I need something like this:
<div ng-repeat="customer in customers">
<select ng-options="option.Name for option in **getOptions(customer.ID)**"></select>
</div>
Is it possible?

Yes , as long as the function is synchronous. Using a filter expression in ng-options is also an alternative
const app = angular.module('myApp', []);
app.controller('myCtrl', function() {
this.getNames = () => ["Emil", "Tobias", "Linus"]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl as $ctrl">
<select ng-model=" $ctrl.selectedName" ng-options="item for item in $ctrl.getNames()" size=5>
</select>
<p ng-if=" $ctrl.selectedName">Selected: {{ $ctrl.selectedName}}</p>
</div>

const app = angular.module('myApp', []);
app.controller('myCtrl', function() {
this.getNames = () => ["Emil", "Tobias", "Linus"]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl as $ctrl">
<select ng-model=" $ctrl.selectedName" ng-options="item for item in $ctrl.getNames()" size=5>
</select>
<p ng-if=" $ctrl.selectedName">Selected: {{ $ctrl.selectedName}}</p>
</div>
Thank you for your answer. But I can't work it. My code below.
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script>
var app = angular.module("MainModule", []);
app.controller('TestController', function ($scope, $http, $filter) {
$scope.one = ["Sam", "Samantha", "George"]
$scope.two = ["Jack", "Sandra", "Bill"]
$scope.getOptions = function (id) {
if (id === 1) {
return $scope.one;
}
else if (id ===2) {
return $scope.two;
}
};
});
</script>
</head>
<body ng-app="MainModule" ng-controller="TestController>
<div>
<select ng-options="item for item in TestController.getOptions(1)"></select>
<select ng-options="item for item in TestController.getOptions(2)"></select>
</div>
</body>
</html>

Related

How to call predefined JavaScript function in ng-change event?

Here's my code, however ng-change is never called. Does anyone know why ? Thanks
<html ng-app="">
<head>
</head>
<body data-ng-init="names=['A', 'B', 'C']">
<script src="resources/js/angular/angular.min.js"></script>
<script src="resources/js/angular/angular.min.js.map"></script>
<select class="form-control input-sm"
ng-model="fda"
ng-change="alert('changed')"
ng-options= "value for value in names" >
</select>
</body>
</html>
You need to have a controller and a corresponding function inside of it,
app.controller("myCtrl", function($scope) {
$scope.alert = function (){
alert("changed");
}
});
DEMO
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.alert = function (){
alert("changed");
}
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<div ng-init="names=['A', 'B', 'C']">
<select class="form-control input-sm" ng-model="fda" ng-change="alert('changed')" ng-options="value for value in names">
</select>
</div>
</body>
</html>
Just add this line in your controller $scope.alert = alert.bind(window);
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.alert = alert.bind(window);
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<div ng-init="names=['A', 'B', 'C']">
<select class="form-control input-sm" ng-model="fda" ng-change="alert('changed')" ng-options="value for value in names">
</select>
</div>
</body>
</html>

angularjs fetch value from textbox after clicking a button only

This is my code
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('myController', function ($scope) {
$scope.getName = function () {
$scope.name = fname;
$scope.lastName = lastName;
};
})
</script>
</head>
<body ng-app="myApp" >
<div >
<input type="text" ng-model="name"/> <br>
<input type="text" ng-model="lastName" />
</div>
<div ng-controller="myController">
<input type="button" value="click" ng-click="getName()" />
<br>
Hello FirstName {{name}}<br>
Last Name {{lastName}}
</div>
</body>
</html>
values are coming while typing into textbox but i want values only after clicking the button.Please help me.
I tried in both ways simple as well as by using service or factory method but no success
You must separate the ng-models of the input texts and destination field. They are updating real-time because of having the same models.
I have created the correct version for you:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('myController', function ($scope) {
$scope.getName = function () {
$scope.nameToSet = $scope.name;
$scope.lastNameToSet = $scope.lastName;
};
})
</script>
</head>
<body ng-app="myApp" >
<div >
<input type="text" ng-model="name"/> <br>
<input type="text" ng-model="lastName" />
</div>
<div ng-controller="myController">
<input type="button" value="click" ng-click="getName()" />
<br>
Hello FirstName {{nameToSet}}<br>
Last Name {{lastNameToSet}}
</div>
</body>
</html>
UPDATE: Here is another version with using a factory:
var myApp = angular.module('myApp', []);
myApp.factory('container', function() {
var model = {
name: '',
lastName: ''
};
return {
model: model,
setName: function(nameToSet) {
model.name = nameToSet;
},
setLastName: function(lastNameToSet) {
model.lastName = lastNameToSet;
}
};
});
myApp.controller('myController', function ($scope, container) {
$scope.$watch('name', function(newvalue,oldvalue) {
container.setName(newvalue);
});
$scope.$watch('lastName', function(newvalue,oldvalue) {
container.setLastName(newvalue);
});
$scope.onNameType = function(value) {
container.setName(value);
};
$scope.onLastNameType = function(value) {
container.setLastName(value);
};
$scope.getName = function () {
debugger;
$scope.nameToSet = container.model.name;
$scope.lastNameToSet = container.model.lastName;
};
})
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
</head>
<body ng-app="myApp" >
<div >
<input type="text" ng-model="name" ng-change="onNameType(name)"/> <br>
<input type="text" ng-model="lastName" ng-change="onLastNameType(lastName)" />
</div>
<div ng-controller="myController">
<input type="button" value="click" ng-click="getName()" />
<br>
Hello FirstName {{nameToSet}}<br>
Last Name {{lastNameToSet}}
</div>
</body>
</html>

How dynamically get the value of a JSON variable in Angular?

Hi I want to do some like this:
{{item.price.{{comparator}}}}
I mean, take a value from type of price using a {{comparator}} variable.
this is an example of my code (the data is bigger and I have more types of prices):
var items = [
{"name":"Item1",price:{public:10,private:15,other1:16.3,other2:17.5}},
{"name":"Item2",price:{public:20,private:45}},
]
var angularApp = angular.module('angularApp', [
'angularAppControllers',
]);
var angularAppControllers = angular.module('angularAppControllers', []);
angularAppControllers.controller('ComparationCtrl', ['$scope',
function ($scope) {
$scope.comparator = "private";
$scope.data = items;
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-App="angularApp">
<div ng-controller="ComparationCtrl">
<select ng-model="comparator">
<option value="public">Public</option>
<option value="private">Private</option>
<option value="other1">Other 1</option>
<option value="other2">Other 2</option>
<option value="othern">....</option>
</select>
{{comparator}}
<br />
<ul>
<li ng-repeat="item in data">
{{item.name}} - {{item.price.public}} - <strong>(item.price.{{comparator}})</strong>
</li>
</ul>
</div>
</div>
Hum, assuming item.price and comparator are defined in your $scope, try:
{{ item.price[comparator] }}
Like this: https://plnkr.co/edit/IrheJrHz8eOfb5LmTx7x
angular.module('app', [])
.config(function() {
})
.controller('ctrl', function($scope) {
$scope.obj = {
"name": "Item1",
"price": {
"public": "10",
"private": "15",
"other1": "16.3",
"other2": "17.5"
}
};
$scope.prop = 'public';
});
And the HTML:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://code.angularjs.org/1.5.8/angular.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body ng-controller="ctrl">
<pre>{{obj.price[prop]|json}}</pre>
<script src="script.js"></script>
</body>
</html>
Basically, {{obj[aPropertyDefinedInScope]}}

unable to get angular ng-repeat group by filter working with dynamic group term

I have been trying for days to get a working version of a grouping filter for Angular. The goal is to group and filter a list of items, using dynamic group and search terms. The end product will have two levels of ng-repeats as well as filter terms, but below I've distilled the core issue to just a single ng-repeat and no search filtering.
The issue is described in this question, namely that I get "10 digest" errors in the JS console. I have tried the suggestion in that thread, namely that I use _.memoize(). This works for the initial load, but somehow doesn't update the ng-repeat when I update the model. I'm also unable to determine how "track by" would work for me.
For example code desired output is:
A selected: "One"
B selected: "tres uno"
Here is the version with digest errors (check the JS console), but with output working as desired:
http://plnkr.co/9TJvZk
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/1.3.0/angular.js" data-semver="1.3.0" data-require="angular.js#*"></script>
<script data-require="underscore.js#*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script>
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}]
return
});
app.filter('myFilter', function() {
return function(items, filter_items) {
return _.groupBy(items, filter_items.group_1);
}
});
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
Group by<br>
<select ng-model="filter_items.group_1">
<option value="propa">A</option>
<option value="propb">B</option>
</select>
<div ng-repeat="(group1, g_items) in items| myFilter:filter_items">
<h2>{{group1}}</h2>
</div>
</div>
</body>
</html>
And error free, but not updating when model does:
http://plnkr.co/N41D2Y
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/1.3.0/angular.js" data-semver="1.3.0" data-require="angular.js#*"></script>
<script data-require="underscore.js#*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script>
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}]
return
});
app.filter('myFilter', function() {
return _.memoize(function(items, filter_items) {
return _.groupBy(items, filter_items.group_1);
}
);
});
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
Group by<br>
<select ng-model="filter_items.group_1">
<option value="propa">A</option>
<option value="propb">B</option>
</select>
<div ng-repeat="(group1, g_items) in items| myFilter:filter_items">
<h2>{{group1}}</h2>
</div>
</div>
</body>
</html>
How do I get working dynamic grouping in AngularJS without the digest errors?
you mean like this
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/1.3.0/angular.js" data-semver="1.3.0" data-require="angular.js#*"></script>
<script data-require="underscore.js#*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script>
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}];
return;
});
app.filter('myFilter', function() {
var m = {};
return function(items, filter_items) {
return (filter_items.group_1 in m) ? m[filter_items.group_1] : (m[filter_items.group_1] = _.groupBy(items, filter_items.group_1) );
}
});
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
Group by<br>
<select ng-model="filter_items.group_1">
<option value="propa">A</option>
<option value="propb">B</option>
</select>
<div ng-repeat="(group1, g_items) in items| myFilter:filter_items">
<h2>{{group1}}</h2>
</div>
</div>
</body>
</html>
I updated the code above as well as the plunker, just to illustrate your code is workable. But this angular-filter project is awesome, check it out.
The reason for the digest error is that each call to _.groupBy returns a new object, so every time angular checks it against the old value it is different, leading to another digest.
As the list is only filtered when filter_items.group_1 changes, it's simple to watch this in the controller and perform the group by there:
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}];
$scope.$watch('filter_items.group_1', function (group) {
$scope.groupedItems = _.groupBy($scope.items, group);
});
});
Then:
<div ng-repeat="(group1, g_items) in groupedItems">
<h2>{{group1}}</h2>
</div>
I believe you can achieve the same result without using a filter. I have successfully achieved this by using a watcher in the controller and grouping in the watcher function. This doesn't have the 10 digest errors and would work when your selection changes.
<head>
<script src="//code.angularjs.org/1.3.0/angular.js" data-semver="1.3.0" data-require="angular.js#*"></script>
<script data-require="underscore.js#*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script>
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}]
$scope.$watch('filter_items.group_1', function(newValue){
$scope.grouped = _.groupBy($scope.items, newValue)
})
return
});
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
Group by<br>
<select ng-model="filter_items.group_1">
<option value="propa">A</option>
<option value="propb">B</option>
</select>
<div ng-repeat="(group1, g_items) in grouped">
<h2>{{group1}}</h2>
</div>
</div>
</body>
</html>

ng-repeat not updating when ng-model input updates

Below I have code example that will successfully group data based on a model property for an ng-repeat, but only on the initial page load. So for example on load I do
$scope.filter_items.group_1 = 'propb'; , which correctly repeats and groups by propb. Same if I switch it to propa.
The problem is that after the page loads, changing the filter_items model via an input has no effect on he ng-repeat, which doesn't update. I've tried to work a bit with the .$apply() method, but nothing that worked (and from what I read I shouldn't have to use it). How can I get the ng-repeat to redraw after a model input change?
Note: I use the memoize function to avoid Angular digest errors, which will happen without it.
http://plnkr.co/N41D2Y
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/1.3.0/angular.js" data-semver="1.3.0" data-require="angular.js#*"></script>
<script data-require="underscore.js#*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script>
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope) {
$scope.filter_items = {};
$scope.filter_items.group_1 = 'propb';
$scope.items = [{id:"1", propa:"one", propb:"uno"},{id:"2", propa:"one", propb:"tres"}]
return
});
app.filter('myFilter', function() {
return _.memoize(function(items, filter_items) {
return _.groupBy(items, filter_items.group_1);
}
);
});
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
Group by<br>
<select ng-model="filter_items.group_1">
<option value="propa">A</option>
<option value="propb">B</option>
</select>
<div ng-repeat="(group1, g_items) in items| myFilter:filter_items">
<h2>{{group1}}</h2>
</div>
</div>
</body>
</html>
I can't get your code working or then there's just something I don't understand or missed. But if custom filter is giving you headache, why don't you just put simple grouping function inside your controller?
Say, your controller
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope) {
$scope.items = [{
id:1,
propa:"one",
propb:"uno"
},{
id:2,
propa:"one",
propb:"uno"
},{
id:3,
propa:"two",
propb:"dos"
},{
id:4,
propa:"two",
propb:"dos"
}];
$scope.notGrouped = angular.copy($scope.items);
$scope.options = ['propa','propb'];
$scope.groupBy = function (option) {
$scope.items = _.groupBy($scope.notGrouped, option);
}
});
and related HTML template
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
Group by<br>
<select ng-model="selectedOption"
ng-options="option as option for option in options"
ng-change="groupBy(selectedOption)">
</select>
<br><br>
<div ng-hide="!!selectedOption">Not grouped yet...</div>
<div ng-repeat="item in items">
<span>{{ item | json }}</span>
</div>
</div>
</body>
Would give you

Resources