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?!
Related
I am new to Angular js and I want to try the following.
I have an Object Array that come from Database. This is the url(example): http://localhost:3000/items/showAll
I have yet implemented the Add, Edit, Update, Delete (Crud operation in backend with nodejs and express js and frontend with angularjs) but my problem is with the checkbox.
I have in a table in my database a field "state", typ boolean default 0 (1 or 0 value).
I have a list of items(for example 100) and want to select with a checkbox in ng-repeat one or more items and send the value(1) to my filed state in the database. My logic is: I need to bind a single item id with the checkbox, then add a value to the checkbox and if is checked send it to the database.
<input type="checkbox" ng-model="state" parse-int ng-true-value="'1'" ng-false-value="'0'" class="form-check-input" >
[{"id":1,"name":"item1","state":0}]
What can I in my controller do?
Updated:
Code: Controller
$scope.createState = function() {
var postItem = {
id : $scope.id,
state : $scope.state
};
itemsService
.createItem(postItem)
.then(
function successCallback(response, data) {
$scope.clearForm();
},
function errorCallback(error, data, status, haders, config) {
console.log("Error getting: " + data);
}
);
};
Service:
var pathItems = "/items/add";
this.createItem = function(postItem) {
return $http.post(pathItems, postItem)
};
html ng-repeat:
<input type="checkbox" ng-true-value="1" ng-false-value="0" ng-model="item.state" ng-click="createState(item.id)">
Update the database, api
addItem: function(item, id, callback) {
return database.query("Update items SET state=? WHERE id=?", [item.state, id], callback);
},
router.post('/update/', function(req, res, next) {
items.addItem(req.body, function(error, count) {
if (error) {
res.json(error);
} else {
res.json(req.body);
}
});
});
This can update the database and I can do this from a bootstrap modal. I wanted to do this with a list of one checkbox per user, but I don't now what to do in AngularJS.
As far as I can understand from your question every time a checkbox is clicked you want to make an API call with the appropriate state. Attach the state to the ng-model of the checkbox. Then on ng-click call a function that will make an API call to update the database,
You can have a look at this code pen for the demo
HTML
<body ng-app="app" ng-controller="controller">
<div ng-repeat="item in data">
{{item.name}}
<input type="checkbox" ng-true-value="1" ng-false-value="0" ng-model="item.state" ng-click="makeAPICall(item.id)"><br>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
</body>
Javascript
angular.module("app", [])
.controller("controller",
function($scope) {
$scope.data = [
{ id: 1, name: "item1", state: 0},
{ id: 2, name: "item2", state: 1},
{ id: 3, name: "item3", state: 0},
{ id: 4, name: "item4", state: 1},
{ id: 5, name: "item5", state: 0}
];
$scope.makeAPICall = function(itemID){
console.log("Item with id "+itemID+" was changed");
// Make API call here
};
}
);
The code updated in my question can update the database. For example, if userID=1, check/uncheck the user and update the database. In Angularjs HTML I can do this with a bootstrap modal. Click to a button and check/uncheck the checkbox.
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 am fairly new to angular and am working with a client that wants a dropdown allowing users to select their neighborhood which is then saved in a cookie to load upon return. I am able to save cookie but am having trouble getting dropdown selected neighborhood to load proper template.
Here is the html:
<select id="mNeighborhood" ng-model="mNeighborhood" ng-options="neighborhood.id as neighborhood.name for neighborhood in neighborhoods" ng-change="saveCookie()"></select>
And then, I have added the following in html:
<div ng-view=""></div>
Here is the app.js code:
var app = angular.module('uSarasota', ['ngCookies', 'ngRoute']);
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
template: '<div><h1 style="margin: 200px;">This is our main page</h1></div>'
})
.when('/downtown', {
templateUrl: "templates/downtown.html"
})
.otherwise({
template: '<div><h1 style="margin: 200px;""><strong>NOTHING TO SEE HERE</strong></h1></div>'
})
});
//Select Neighborhood
app.controller('myNeighborhood', ['$scope', '$cookies', function($scope, $cookies) {
$scope.neighborhoods = [{
name: "My Neighborhood",
id: 0
}, {
name: "All of Sarasota",
id: 1
}, {
name: "Downtown",
url: "/downtown",
id: 2,
}, {
name: "North Sarasota",
id: 3
}, {
name: "Lakewood Ranch",
id: 4
}, {
name: "Longboat Key",
id: 5
}, {
name: "St. Armands Circle",
id: 6
}, {
name: "Southside Village",
id: 7
}, {
name: "Siesta Key",
id: 8
}, {
name: "Gulf Gate",
id: 9
}];
//Set Cookie so when user returns to site, it will be on their neighborhood
$scope.mNeighborhood = parseInt($cookies.get('sNeighborhood')) || 0;
$scope.saveCookie = function() {
$cookies.put('sNeighborhood', $scope.mNeighborhood);
};
}]);
This all works fine to save and load user selection, but am having trouble finding solution to get template based on selection. So, should I add url to the array for each neighborhood and if so, how do I get the link?
Basically you need to change the URL programatically on selection of dropdown. For achieving this thing you need to first change you ng-options to return object on selection. And then using that object get url property from it to load particular template.
Markup
<select id="mNeighborhood"
ng-model="mNeighborhood"
ng-options="neighborhood.name for neighborhood in neighborhoods"
ng-change="saveCookie()">
</select>
Code
$scope.saveCookie = function() {
var mNeighborhood = $scope.mNeighborhood;
$cookies.put('sNeighborhood', mNeighborhood.id);
//do add $location dependency in controller function before using it.
$location.path(mNeighborhood.url);
};
Update
On initial Load the value should be set as object as per new implementation.
$scope.mNeighborhood = {}; //at the starting of controller
//the other code as is
//below code will get the object from the neighborhoods array.
$scope.mNeighborhood = $filter('filter')($scope.neighborhoods, parseInt($cookies.get('sNeighborhood')) || 0, true)[0];
$scope.saveCookie = function() {
var mNeighborhood = $scope.mNeighborhood;
$cookies.put('sNeighborhood', mNeighborhood.id);
//do add $location dependency in controller function before using it.
$location.path(mNeighborhood.url);
};
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 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);
};