I have a User object in Angular controller. I also have an array of Account objects with respective ID for each.
In User I have a field "default_account" where I want to put ID of a default account. So, user can have a lot of accounts but only one of them can be default. When I go to Account options, I have a checkbox there which is responsible for setting/unsetting the account as default.
Now I want to set checkbox on/off depending on its being default for the user. And I also need to respectively change default_account field inside User object on checkbox change. It puzzles me quite much how I can do it.
Any advice is appreciated!
Very approximate (didn't text that):
html:
<div ng-repeat="account in accounts">
<input type="checkbox" ng-checked="account == user.default_acount"
ng-click="SelectAssDefault(account )" />
</div>
js:
function MyCtrl($scope) {
$scope.user = { name: 'user', default_acount: null};
$scope.accounts = [{ }, { }, ...];
$scope.SelectAssDefault = function (account) {
$scope.user.default_acount = account;
};
}
EDIT: a working example: http://jsfiddle.net/ev62U/120/
If you want to set a checkbox to true based on a variable, you can set ng-checked="variable" within the input tag.
If the variable is true the box will be checked. If it's false it won't. Alternatively, an expression will also work e.g. ng-checked="1===1" will evaluate to true.
If you want to alter something else based on user clicking on the checkbox, set ng-click="someCtrlFunction()" within the input tag. This will call a function in your controller. You can look up the value of the checkbox from your controller if you've bound to it.
Here's a fiddle: http://jsfiddle.net/E8LBV/10/ and here's the code:
HTML
<div ng-app="App">
<div ng-controller="AppCtrl">
<ul>
<li ng-repeat="user in users">{{user.name}}
<ul>
<li ng-repeat="account in user.accounts">
<input type="checkbox" ng-model="checked" ng-checked="account == user.default" ng-click="changeDefault(user.id,account,checked)">{{account}}</input>
</li>
<ul/>
</li>
</ul>
</div>
</div>
JS
var app = angular.module('App', []);
app.service('Users', function () {
var Users = {};
Users.data = [{
'id': 1,
'name': 'jon',
'default': null
}, {
'id': 2,
'name': 'pete',
'default': null
}];
return Users;
});
app.service('Accounts', function () {
var Accounts = {};
Accounts.data = [{
'user': 1,
'ac': 123456
}, {
'user': 2,
'ac': 456832
}, {
'user': 2,
'ac': 345632
}, {
'user': 1,
'ac': 677456
}];
return Accounts;
});
app.controller('AppCtrl', function ($scope, Users, Accounts) {
$scope.users = Users.data;
//attach accounts to user
for (i = 0; i < $scope.users.length; i++) {
$scope.users[i].accounts = [];
for (ii = 0; ii < Accounts.data.length; ii++) {
if (Accounts.data[ii].user == $scope.users[i].id) {
$scope.users[i].accounts.push(Accounts.data[ii].ac);
}
}
}
//function to change the default account for the user
$scope.changeDefault = function (id, account, checked) {
if (!checked) {
return;
}
for (i = 0; i < $scope.users.length; i++) {
if ($scope.users[i].id == id) {
$scope.users[i].
default = account;
}
}
}
});
Here is my solution that perfectly worked for me!
<tbody ng-repeat="account in accounts">
<tr>
<td ><a ng-click="getloandetails(account.idAccount)">{{account.accountName}}</a></td>
<td>$ {{account.currentBalance}}</td>
</tr>
</tbody>
and in Angular side just do this:
$scope.getloandetails = function(accountId) {
alert('Gettring details for the accountId: ' + accountId);
};
Related
I want to filter object inside nested ng-repeat.
HTML:
<div ng-controller="MyController">
<input type="text" ng-model="selectedCityId" />
<ul>
<li ng-repeat="shop in shops">
<p ng-repeat = "locations in shop.locations | filter:search" style="display: block">
City id: {{ locations.city_id }}
<span style="padding-left: 20px; display: block;" ng-repeat="detail in locations.details | filter:item">Pin code: {{detail.pin}}</span>
</p>
</li>
</ul>
Controller:
var myApp = angular.module('myApp', []);
myApp.controller('MyController', function ($scope) {
$scope.search = function (location) {
if ($scope.selectedCityId === undefined || $scope.selectedCityId.length === 0) {
return true;
}
if (location.city_id === parseInt($scope.selectedCityId)) {
return true;
}
};
$scope.item = function (detail) {
if ($scope.selectedCityId === undefined || $scope.selectedCityId.length === 0) {
return true;
}
if (detail.pin == parseInt($scope.selectedCityId)) {
return true;
}
};
$scope.shops =
[
{
"category_id":2,
"locations":[
{
"city_id":368,
"details": [{
"pin": 627718,
"state": 'MH'
}]
}
]
},
{
"name":"xxx",
"category_id":1,
"locations":[
{
"city_id":400,
"region_id":4,
"details": [{
"pin": 627009,
"state": 'MH'
},{
"pin": 129818,
"state": 'QA'
}]
},
]
},
];
});
Here's the fiddle:
http://jsfiddle.net/suCWn/210/
I want to use multiple filter inside ng-repeat.
Example: Whenever user enters the ID in the input box. The list should filter based on cityID or PinCode.
if user enter '129818' it should show pin code result of 129818 along with its parent cityID
Similarly, if a user enter 400, the list should filter and show cityID result with 400 along with its child pin code.
EDIT:
Update Code http://codepen.io/chiragshah_mb/pen/aZorMe?editors=1010]
First, you must not filter locations with matching details. Use something like this in the search filter:
$scope.search = function (location) {
var id = parseInt($scope.selectedCityId);
return isNaN(id) || location.city_id === id ||
location.details.some(function(d) { return d.pin === id });
};
To show details if filtered by cityID, you have to find the parent location and check if it was filtered.
$scope.item = function (detail) {
var id = parseInt($scope.selectedCityId);
return isNaN(id) || detail.pin === id || locationMatches(detail, id);
};
function locationMatches(detail, id) {
var location = locationByDetail(detail);
return location && location.city_id === id;
}
function locationByDetail(detail) {
var shops = $scope.shops;
for(var iS = 0, eS = shops.length; iS != eS; iS++) {
for(var iL = 0, eL = shops[iS].locations.length; iL != eL; iL++) {
if (shops[iS].locations[iL].details.indexOf(detail) >= 0) {
return shops[iS].locations[iL];
}
}
}
}
EDIT Another, more flexible solution would be to remove all the filters from ngRepeats and do the filtering in a method that you call on ngChange of the search text. Here is the basic structure for this approach.
myApp.controller('MyController', function($scope, $http) {
var defaultMenu = [];
$scope.currentMenu = [];
$scope.searchText = '';
$http.get(/*...*/).then(function (menu) { defaultMenu = menu; } );
$scope.onSearch = function() {
if (!$scope.searchText) {
$scope.currentMenu = defaultMenu ;
}
else {
// do your special filter logic here...
}
};
});
And the template:
<input type="text" ng-model="searchText" ng-change="onSearch()" />
<ul>
<li ng-repeat="category in currentMenu">
...
</li>
</ul>
I have updated your filters. The problem is in your search filter you are only checking for the city_id, what you should do is:
Check if the typed id is city_id
Check if typed id is a pid of a child detail of given location
Similar thing for the item filter:
Check if the typed id is a pid of the detail being filtered
Check if the typed id is a city_id of the parent location of the detail passed in
Here is a working jsFiddle. I hope this helps.
By simply modifying the JSON to include the city_id for children so you don't need to loop through it to get the parent's city_id, the solution is as easy as this:
var myApp = angular.module('myApp', []);
myApp.controller('MyController', function ($scope) {
$scope.search = function (location) {
if (!$scope.selectedCityId)
return true;
//if user's input is contained within a city's id
if (location.city_id.toString().indexOf($scope.selectedCityId) > -1)
return true;
for (var i = 0; i < location.details.length; i++)
//if user's input is contained within a city's pin
if (location.details[i].pin.toString().indexOf($scope.selectedCityId) > -1)
return true;
};
$scope.item = function (detail) {
if (!$scope.selectedCityId)
return true;
//if user's input is contained within a city's id
if (detail.city_id.toString().indexOf($scope.selectedCityId) > -1)
return true;
//if user's input is contained within a city's pin
if (detail.pin.toString().indexOf($scope.selectedCityId) > -1)
return true;
};
Modified JSON
$scope.shops=[{"category_id":2,"locations":[{"city_id":368,"details":[{"city_id":368,"pin":627718,"state":'MH'}]}]},{"name":"xxx","category_id":1,"locations":[{"city_id":400,"region_id":4,"details":[{"city_id":400,"pin":627009,"state":'MH'},{"city_id":400,"pin":129818,"state":'QA'}]},]},];});
If directly modifying the JSON is not possible, you can modify it like this in this controller directly after this $scope.shops = ...json... statement:
for(var i=0; i<$scope.shops.length; i++)
for(var j=0, cat=$scope.shops[i]; j<cat.locations.length; j++)
for(var k=0, loc=cat.locations[j]; k<loc.details.length; k++)
loc.details[k].city_id=loc.city_id;
Working fiddle:
http://jsfiddle.net/87e314a0/
I tried to make the solution easier to understand :
index.html :
<div ng-controller="MyController">
<input type="text" ng-model="search.city_id" />
<ul>
<li ng-repeat="shop in shops">
<p ng-repeat = "locations in shop.locations | filter:search.city_id" style="display: block">
City id: {{ locations.city_id }}
<span style="padding-left: 20px; display: block;" ng-repeat="detail in locations.details | filter:item">Pin code: {{detail.pin}}</span>
</p>
</li>
</ul>
</div>
app.js :
var myApp = angular.module('myApp', []);
myApp.controller('MyController', function ($scope) {
$scope.shops =
[
{
"category_id":2,
"locations":[
{
"city_id":368,
"details": [{
"pin": 627718,
"state": 'MH'
}]
}
]
},
{
"name":"xxx",
"category_id":1,
"locations":[
{
"city_id":400,
"region_id":4,
"details": [{
"pin": 627009,
"state": 'MH'
},{
"pin": 129818,
"state": 'QA'
}]
},
]
},
];
});
Here's the fiddle :
mySolution
I have the following array:
[{
"Id": 3,
"Name": "A"
},
{
"Id": 3,
"Name": "B"
},
{
"Id": 3,
"Name": "C"
}]
I am using this in the following Angular view:
<select ng-model="selectedCategory" ng-options="category.Name for category in categories"></select>
<pre>{{selectedCategory | json}}</pre>
<button type="button" ng-click="move()">Move</button>
The controller looks like:
var moveCategoryController = function ($scope, category, categoriesService) {
var getCategories = function () {
categoriesService.getCategories()
.success(function (result) {
$scope.categories = [];
for (var i = 0; i < result.Results.length; i++) {
var cat = result.Results[i];
if (cat.Id !== category.Id) {
$scope.categories.push(cat);
}
}
$scope.selectedCategory = $scope.categories[0];
})
.error(function () {
$scope.errorMessage = "There was a problem loading the categories.";
});
};
getCategories();
$scope.move = function () {
alert($scope.selectedCategory.Name);
};
}
bpApp.controller("moveCategoryController", moveCategoryController);
For info, the category object injected into the controller is a category object (the controller is being used in a modal and the category is passed to it from the parent page).
The Problem
On loading, the select is bound to the data fine, and when the user changes the select list the <pre> content updates correctly with the newly selected category.
The problem is when I click the Move button, which calls the move() function on the controller scope, the selectedCategory property of the scope has not been updated. For example, if I select the category "B", the alert still pops up with "A".
So, it seems that the ng-model is updated in the view, but not in the controller?!
I have a table with these fields: product, lot, input1, input2. You can clone a line, and you can add a new line.
What I want to do is that for each row you can add a new Lot created by a "number" and by "id" that user write in the input field under the Select lot. And I wanted that the script add the new Lot in the json data and the lot 's option list.
This is the function for add that I tried to do:
$scope.addLot = function() {
var inWhichProduct = row.selectedProduct;
var newArray = {
"number": row.newLot.value,
"id": row.newLot.id
};
for (var i = 0; i < $scope.items.length; i++) {
if ($scope.items[i].selectedProduct === inWhichProduct) {
$scope.items[i].selectedLot.push(newArray);
}
}
};
-->> THIS <<-- is the full code.
Can you help me?
I think your question is a little too broad to answer on Stack Overflow, but here's an attempt:
<div ng-app="myApp" ng-controller="myCtrl">
<table>
<tr ng-repeat="lot in lots">
<td>{{ lot.id }}</td>
<td>{{ lot.name }}</td>
</tr>
</table>
<p>name:</p> <input type="text" ng-model="inputName">
<p>id:</p> <input type="text" ng-model="inputId">
<button ng-click="addLotButton(inputId, inputName)">Add</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.2/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.lots = [{
name: "test",
id: 1
},
{
name: "test2",
id: 2
}
];
$scope.addLot = function(lotId, lotName) {
var newLotObject = {
name: lotName,
id: lotId
};
$scope.lots.push(newLotObject);
};
$scope.addLotButton = function(id, name) {
$scope.addLot(id, name);
};
$scope.addLot(3, "Another test");
});
</script>
Basically this code just takes some input and adds an object to the scope for that input. The table is created using an ng-repeat of this data. It's not great code at all but it's just a quick example.
The push method adds newArray to selectedLot array. It's not working on the JSON data but on arrays. If you want to have the JSON, you can give a try to :
var myJsonString = JSON.stringify(yourArray);
It will create a JSON string based on the parameter
Maybe you should try to structure your data to make lots as properties of products.
{
products: [
{id: 1, lots: [{id:1}, {id:2}]},
{id: 2, lots: [{id:1}, {id:2}]}
]
}
To add a lot to a product :
product = products[0];
product.lots.push(newArray);
Change the fallowing:
html:
<button ng-click="addLot(row.selectedProduct.id,row.newLot.value,row.newLot.id)">Add</button>
js:
$scope.addLot = function(id,val,lotId) {
// console.log(id);
var inWhichProduct = id;
var newArray = { "value": val, "id": lotId };
//console.log($scope.items)
angular.forEach($scope.items,function(v,i){
if($scope.items[i].id == id )
{
$scope.items[i].lots.push(newArray);
console.log($scope.items[i].lots);
}
});
};
http://plnkr.co/edit/W8eche8eIEUuDBsRpLse?p=preview
I have a select box which is populated with some data from my controller. When an input value changes the contents of the select box should be filtered and a default value should be assigned based on the is default property of the data object.
Is there any way this can be done using angular directives or would it need to be done as a custom filter function doing something along the lines of
angular.forEach(vm.data,function(item){
if (vm.q == item.someId && item.isDefault) {
vm.result = item.value;
}
});
My html looks something like
<div ng-app="myApp" ng-controller="ctrl as vm">
<input type="text" ng-model="vm.q">
<select ng-options="item.value as item.description for item in vm.data | filter:{someId:vm.q}" ng-model="vm.result"></select>
</div>
and my controller looks like:
(function(){
angular.module('myApp',[]);
angular
.module('myApp')
.controller('ctrl',ctrl);
function ctrl()
{
var vm = this;
vm.data = [
{
someId: '1',
description: 'test1',
value: 100,
isDefault: true
},
{
someId: '2',
description: 'test2',
value: 200,
isDefault: false
},
{
someId: '3',
description: 'test3',
value: 100,
isDefault: true
},
];
}
})();
See my plunkr demo here: http://plnkr.co/edit/RDhQWQcHFMQJvwOyHI4r?p=preview
Desired behaviour:
1) Enter 1 into text box
2) List should be filtered to 2 items
3) Select box should pre-select item 1 based on property isDefault set to true
Thanks in advance
I'd suggest you include some 3rd party library, like lodash, into your project to make working with arrays/collections that much easier.
After that you could add ng-change directive for your input.
<input type="text" ng-model="vm.q" ng-change="vm.onChange(vm.q)">
And the actual onChange function in the controller
vm.onChange = function(id) {
var item = _.findWhere(vm.data, { someId: id, isDefault: true });
vm.result = item ? item.value : null;
};
And there you have it.
This is difficult to phrase but:
I have 1 collection called users.
Every user has 3 properies: id, name, skill.
{
_id: 1,
name: 'frank young',
skill: 'java'
},
I have 1 form collects search results upon pressing enter.
<form ng-submit="pushToNewArry(searchTerm)">
<input type="text" ng-model="searchTerm" />
<input type="submit">
</form>
this is not the best way to do this
$scope.newUsers = [];
$scope.pushToNewArry = function(msg) {
$scope.trackedUsers.push(msg);
$scope.searchTerm = '';
};
Question:
How do I create a filter that will run over multiple search terms and create a list proper matches based on the users collections vs inputed values.
<ol ng-repeat = "user in users | filter: trackedUsers">
<li class="names"><span>{{$index}}. </span>{{user.name}}</li>
<li class="skills">{{user.skill}}</li>
</ol>
Upon submission, the user input will be saved and create a new array of users based on inputed values of search. therefore, multiple matching values.
Updated:
JSFiddle
not excatly the same as example above because I keep playing with it.
You mean like this jsfriddle
updated fiddle
updated fiddle2
<div>{{listSearchTerms | json}}</div>
<form ng-submit="saveSearchTerm()">
<input type="text" ng-model="searchTerm" />
<input type="submit">
</form>
<ol ng-repeat = "user in users | filter:filterSearch(searchTerm)">
<li class="names"><span>{{$index}}. </span>{{user.name}}</li>
<li class="skills">{{user.skill}}</li>
</ol>
Javascript
var app = angular.module('app', []);
//App.directive('myDirective', function() {});
//App.factory('myService', function() {});
app.controller('MainCtrl', function ($scope) {
$scope.users = [
{
_id: 1,
name: 'frank young',
skill: 'java'
},
{
name: 'jeff qua',
skill: 'javascript'
},
{
name: 'frank yang',
skill: 'python'
},
{
name: 'ethan nam',
skill: 'python'
},
{
name: 'ethan nam',
skill: 'javascript'
},
];
$scope.searchTerm = "";
$scope.listSearchTerms = [];
$scope.filterSearch = function (terms) {
return function (item) {
return terms.length < 1 ? true :
terms.reduce(function (lastresult, term) {
return lastresult + (item.name.indexOf(term) > -1 || item.skill.indexOf(term) > -1);
}, 0) > 0;
}
};
$scope.saveSearchTerm = function () {
$scope.listSearchTerms.push($scope.searchTerm);
$scope.searchTerm = "";
}
});