Angular Two Way Data Binding Not Working While Using HTTP - angularjs

I am using ControllerAs in angular with ui.router, I have an API in PHP when I call the API and set the scope variable by vm approach for templates then it works accordingly and when I want to delete some record set
and update the vm.servers variable again then template not change according to the newly updated object.
function serverController( server, $state, $rootScope, $scope)
{
var vm = this;
vm.delete = function(server_id) {
vm.loader = false;
server.delete('server/' + server_id)
.then(
function(response){
if(response.status === 200 && !response.data.status) {
alert(response.data.message);
} else if(response.status === 200 && response.data.status){
server.setRootScope().then(
function(){
vm.servers = $rootScope.servers;
$state.go($state.current, {}, {reload: true});
}
);
}
}, function(response) {
if(response.status === 401) {
$state.go('login');
}
}
);
};
if($rootScope.servers == undefined) {
server.get('server')
.then(
function (response) {
if (response.status === 200) {
vm.servers = response.data;
$rootScope.servers = {};
angular.forEach(response.data, function (val) {
if('running' === val.status) {
val['serverState'] = true;
} else {
val['serverState'] = false;
}
$rootScope.servers[val.id] = val;
});
}
},
function (response) {
if (response.status === 401) {
$state.go('login');
}
});
} else {
vm.servers = $rootScope.servers;
}
}
Template File.
<table class="table movietable" width="70%" border="1">
<tr ng-repeat="server in serverModel.servers">
<td width="85%">
<table>
<tr>
<td><b>Server Label: </b> {{server.label}}</td>
</tr>
<tr>
<td>Status: {{server.status}}</td>
</tr>
<tr>
<td>Created At: {{server.created_at}}</td>
</tr>
</table>
</td>
</tr>
</table>

I look your code. I found a problem that,
You are not updating the vm.servers with
the response data. As the values in $rootScope.servers might
be older. So with every delete function call you will have to either update the $rootScope.servers or vm.servers with new data.
I have create a small demo from your code, hope it will help you
identify the problem. In this demo I have first load the data in table
after this, on a button click deleting the record by id and updating
the vm.servers.
My Controller
.controller('Controller',['$rootScope', function($rootScope) {
var vm =this;
vm.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
vm.delete = function(server_id) {
vm.loader = false;
// added some value to $rootScope.servers or you can update it with response data. This is where you will need to update your logic.
$rootScope.servers = [
{ id: 1,
name: 'Naomi1',
address: '1600 Amphitheatre1'
},
{
id: 2,
name: 'Naomi2',
address: '1600 Amphitheatre2'
}
];
angular.forEach($rootScope.servers, function(value,key) {
if(value.id == server_id) {
$rootScope.servers.splice(key,1);
}
});
console.log($rootScope.servers);
//Here I have assign new $rootScope.servers.
vm.servers = $rootScope.servers;
};
var val = {};
vm.init = function() {
vm.servers = [{
id: 1,
name: 'Naomi1',
address: '1600 Amphitheatre1'
},{
id: 2,
name: 'Naomi2',
address: '1600 Amphitheatre2'
}];
$rootScope.servers = {};
val['serverState'] = true;
$rootScope.servers[val.id] = val;
}
vm.init();
}])
index.html
<div ng-controller="Controller as vm">
<table class="table movietable" width="70%" border="1">
<tr>
<td width="85%">
<table>
<tr ng-repeat="server in vm.servers">
<td><b>Server Label: </b> {{server.name}}</td>
<td>Status: {{server.address}}</td>
<td><button ng-click="vm.delete(server.id);">Delete</button></td>
</tr>
</table>
</td>
</tr>
</table>
</div>
Hope this will help you !
Cheers,
Jimmy

Related

TypeError: v2.UpdataData is not a function

I am new to Angular and MVC , and I have created a code for display
records into table view.
User can edit and delete that records by clicking the Edit and Delete
Link
but it shows me error when i click on edit link TypeError:
v2.UpdataData is not a function
and it also shows me error TypeError: $http.get is not a function
when i click on Delete Link
Can anyone help me to solve this out. Thanks in advance.
Controller.js
//update data of table
$scope.UpdataData = [];
//UpdateData();
$scope.UpdateData = function (StateMaster) {
var RetValData = DataService.UpdateStudent(StateMaster);
debugger;
getData.then(function (StateMaster) {
debugger;
StateID: $scope.StateID;
StateName: $scope.StateName;
CountryName: $scope.CountryName;
}, function () {
alert('Error in getting records');
});
}
$scope.DeleteData = [];
$scope.DeleteData = function (r, index) {
var retval = DataService.DeleteData(r.StateID).success(function (msg) {
$scope.countrydata.splice(index, 1);
alert('Student has been deleted successfully.');
}).error(function () {
alert('Oops! something went wrong.');
});
}.factory('DataService', function ($http) {
var fac={}
debugger;
fac.UpdateData= function($http)
{
return $http.get('/State/UpdateData');
}
return fac;
}).factory('DataService', function () {
var fac={}
debugger;
fac.DeleteData = function ($http)
{
return $http.get('/State/DeleteData');
}
return fac;
});
StateController.cs
public string UpdateData(StateMaster r)
{
if (r != null)
{
using (simpleEntities dbContext = new simpleEntities())
{
StateMaster lstdata = dbContext.StateMasters.Where(x => x.StateID == r.StateID).FirstOrDefault();
lstdata.StateName = r.StateName;
lstdata.CountryName = r.CountryName;
dbContext.SaveChanges();
return "Data Updated";
}
}
else
{
return "something went worng";
}
}
[HttpPost]
public string DeleteData(int id)
{
if (id != 0)
{
using (simpleEntities databContext = new simpleEntities())
{
var lsdata = databContext.StateMasters.Where(x => x.StateID == id).FirstOrDefault();
databContext.StateMasters.Remove(lsdata);
databContext.SaveChanges();
return "Data Deleted Successfully";
}
}
else {
return "Error Occured";
}
}
InsertState.cshtml
<div ng-app="MyApp" ng-controller="StateController">
<table class="table table-bordered">
<tr>
<td>Sr. No.</td>
<td>Country Name</td>
<td>State Name</td>
<td></td>
#*<td>Country Name</td>*#
</tr>
<tr ng-repeat="r in countrydata">
<td>{{$index + 1}}</td>
<td>{{r.CountryName}}</td>
<td>{{r.StateName}}</td>
#*<td>{{r.CountryName}}</td>*#
<td>
<span ng-click="UpdataData(r)" class="btnAdd">Edit</span> |
<span ng-click="DeleteData(r)" class="btnRed">Delete</span>
</td>
</tr>
</table>
</div>
there is problem in you code with this
line $scope.UpdateData = function (StateMaster
as you are trying to run fuction of your $scop but fuction is of factory so you have to try like
factory.UpdateDate
Seem like there is problem in defining factory in angular , you can try below way
var app = angular.module('myApp', []);
app.factory('testFactory', function(){
return {
sayHello: function(text){
return "Factory says \"Hello " + text + "\"";
},
sayGoodbye: function(text){
return "Factory says \"Goodbye " + text + "\"";
}
}
});
function HelloCtrl($scope, testService, testFactory)
{
$scope.fromFactory = testFactory.sayHello("World");
}
you can place your function and just try out it return you value or not

How to use select filter with static values on async (server-side) ngTable

I'm using ngTable 0.3.3 and am doing a async call to populate the table (pagination also done on server side). Here's my code:
var data = [];
$scope.tableParams = new ngTableParams({
page: 1,
count: 10
}, {
getData: function($defer, params) {
// getData gets called when you click on a different page in the pagination links.
// get the page number and size from params.$params
var pageNumber = params.$params.page;
var pageSize = params.$params.count;
// set up the query parameters as expected by your server
var mm = params.filter();
var queryParams = {"page_size":pageSize, "page_number":pageNumber, "sorting": params.sorting(), role: mm.role, id: mm.id, email: mm.email};
$log.log(mm.role);
// $log.log(mm.role, mm.email);
User.getCount().then(function (total) {
User.query(queryParams).then(function (result) {
params.total(total);
$defer.resolve(result);
});
});
}
});
with this html:
<table ng-table="tableParams" show-filter="true" class="table table-custom">
<tr ng-repeat="user in $data">
<td data-title="'Name'">
{{user.first_name}} {{user.last_name}}
</td>
<td data-title="'Role'" sortable="'role'" filter="{ 'role': 'text' }">
{{user._role}}
</td>
<td data-title="'Email'" sortable="'email'" filter="{ 'email': 'text' }">
{{user.email}}
</td>
<td data-title="'Created date'">
{{user.created_at | date: 'dd MMM yyyy'}}
</td>
<td data-title="'Edit'">
<a ui-sref="app.users.edit({userId: user.id})">Edit</a>
</td>
<td data-title="'Edit'">
<a ng-click="deleteUser(user.id)">Delete</a>
</td>
</tr>
</table>
And both filtering and pagination works as expected. You can see I have a $log call which tells me when the filter is being triggered while I type in the text field. Now I'm trying to get the role as a select rather than a text field, so I changed my code like so:
$scope.roles = function (column) {
var def = $q.defer();
var docType = [{role: 'admin'}, {role: 'customer'}, {role: 'singer'}, {role: 'voiceArtist'}];
def.resolve(docType);
return def;
};
var data = [];
$scope.tableParams = new ngTableParams({
page: 1,
count: 10
}, {
getData: function($defer, params) {
// getData gets called when you click on a different page in the pagination links.
// get the page number and size from params.$params
var pageNumber = params.$params.page;
var pageSize = params.$params.count;
// set up the query parameters as expected by your server
var mm = params.filter();
var queryParams = {"page_size":pageSize, "page_number":pageNumber, "sorting": params.sorting(), role: mm.role, id: mm.id, email: mm.email};
$log.log(mm.role);
// $log.log(mm.role, mm.email);
User.getCount().then(function (total) {
User.query(queryParams).then(function (result) {
params.total(total);
$defer.resolve(result);
});
});
}
});
And this html:
<table ng-table="tableParams" show-filter="true" class="table table-custom">
<tr ng-repeat="user in $data">
<td data-title="'Name'">
{{user.first_name}} {{user.last_name}}
</td>
<td data-title="'Role'" sortable="'role'" filter="{ 'role': 'text' }">
{{user._role}}
</td>
<td data-title="'Role1'" filter="{role: 'select'}" filter-data="roles($column)">{{user._role}}</td>
<td data-title="'Email'" sortable="'email'" filter="{ 'email': 'text' }">
{{user.email}}
</td>
<td data-title="'Created date'">
{{user.created_at | date: 'dd MMM yyyy'}}
</td>
<td data-title="'Edit'">
<a ui-sref="app.users.edit({userId: user.id})">Edit</a>
</td>
<td data-title="'Edit'">
<a ng-click="deleteUser(user.id)">Delete</a>
</td>
</tr>
</table>
The roles (that I want to populate the select from) is a static array with five elements in it. I can see the select on the Role column, but is empty (doesn't show admin, customer, etc) and it doesn't trigger the filter. When I select an item, nothing happens anywhere. Wha am I missing here?
PS: I've seen similar questions and have even tried their plunker when was available, but the questions I've found they either use async values for the select (which I don't want to) or the whole data is static, which again, I don't want to. Any help would be much appreciated.
EDIT
How I got it to work:
My js code:
$scope.roles = function (column) {
var def = $q.defer();
var docType = [{id: 'admin', title: 'Admin'}, {id: 'customer', title: 'Customer'}, {id: 'singer', title: 'Singer'}, {id: 'voiceArtist', title: 'Voice Artist'}];
def.resolve(docType);
return def;
};
var data = [];
$scope.deleteUser = function (id) {
User.get(id).then(function (result) {
$scope.tmpUser = result;
$scope.tmpUser.remove().then(function (result) {
if (result) {
$scope.showAlert('User deleted successfully.', 'success');
var n = true;
angular.forEach(data, function (v, k) {
if ($scope.tmpUser.id === v.id) {
if (n) {
data.splice(k, 1);
$scope.tableParams.reload();
n = false;
}
}
});
}
});
});
};
$scope.tableParams = new ngTableParams({
page: 1,
count: 10
}, {
getData: function($defer, params) {
// getData gets called when you click on a different page in the pagination links.
// get the page number and size from params.$params
var pageNumber = params.$params.page;
var pageSize = params.$params.count;
// set up the query parameters as expected by your server
var mm = params.filter();
var queryParams = {"page_size":pageSize, "page_number":pageNumber, "sorting": params.sorting(), role: mm.role, id: mm.id, email: mm.email};
User.getCount().then(function (total) {
User.query(queryParams).then(function (result) {
params.total(total);
$defer.resolve(result);
});
});
}
});
Its important to note that the array you pass must in the format of [{id:'someId', title: 'SomeTitle'}, {...}]
Your select is not populated because you're not waiting for the promise to resolve.
Here's a plunker that I stumbled upon when I faced this issue a few months ago:
plnkr.co/edit/XJo9rp?p=preview
Try something like that:
function getData() {
return $q.when([{role: 'admin'},...]);
}
var promise = getData();
Which is the short version for:
function getData() {
var def = $q.defer();
var docType = [{role: 'admin'},...];
def.resolve(docType);
return def;
}
var promise = getData();
and your scope function:
$scope.roles = function(column) {
var select = promise.then(function(results) {
return results;
})
return select;
};

Add, Remove & Update specific data In JSON in AngularJS

I have pulled data from json file. Now its displayed over DOM.
On HTML Page, I have three option 1) Edit Data 2) Delete Particular Data & 3) Add New Data.
How to perform this using AngularJS Code? i.e. on editing name, it should update my JSON object. On Deleting row, it should delete that row in JSON data. and also If I click on Add New, then entered data will be added to JSON.
My Code is as below.
Importing data through json file and displaying on DOM
.controller('MainCtrl', function ($scope, $http) {
$http.get('data/home.json').
success(function(data, status, headers, config) {
$scope.details = data;
}).
error(function(data, status, headers, config) {
// log error
});
});
Output of this code is correct as below image.
JSON Object as below.
{
"status":"success",
"adformat":[
{
"adformat_id":1,
"name":"Format 1",
"size":"300x250"
},
{
"adformat_id":2,
"name":"Format 2",
"size":"320x250"
},
{
"adformat_id":3,
"name":"Format 3",
"size":"320x480"
}
]
}
I would do it like this:
MainCtrl.js
(function () {
'use strict';
angular
.module('app')
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope', 'MainFactory'];
function MainCtrl($scope, MainFactory) {
$scope.details = MainFactory.details;
function init() {
MainFactory.get();
}
init();
$scope.detailsModel = {
"adformat_id": 1,
"name": "Format 1",
"size": "300x250"
};
$scope.add = function () {
$scope.details.push($scope.detailsModel);
};
$scope.delete = function (index) {
$scope.details.splice(index, 1);
};
$scope.edited = -1;
$scope.editedModel = {
"adformat_id": 0,
"name": "",
"size": ""
};
$scope.edit = function (index) {
$scope.edited = index;
};
$scope.finishEdit = function (index) {
$scope.details[index] = $scope.editedModel;
$scope.edited = -1;
};
}
})();
MainFactory.js
(function () {
'use strict';
angular
.module('app')
.factory('MainFactory', MainFactory);
MainFactory.$inject = [];
function MainFactory() {
var self = this;
self.details = [];
self.get = $http.get('data/home.json')
.then(function (response) {
self.details = response.data;
}).catch(function (error) {
// log error
});
return self;
}
})();
index.html
<div ng-app="app">
<div ng-controller="MainCtrl">
<table>
<tbody>
<tr ng-repeat="details in detail">
<!-- show-->
<td ng-hide="edited === $index">{{detail.adformat_id}}</td>
<td ng-hide="edited === $index">{{detail.name}}</td>
<td ng-hide="edited === $index">{{detail.size}}</td>
<td ng-hide="edited === $index">
<button ng-click="edit($index)">Edit</button>
<button ng-click="delete($index)">Detele</button>
</td>
<!-- Edit-->
<td ng-show="edited === $index">{{detail.adformat_id}}</td>
<td ng-show="edited === $index"><input type="text" ng-model="editedModel.name"></td>
<td ng-show="edited === $index"><input type="number" ng-model="editedModel.size"></td>
<td ng-show="edited === $index">
<button ng-click="finishEdit($index, editedModel)">Save</button>
<button ng-click="delete($index)">Detele</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>
<button ng-click="add()">Add</button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
It is just prototype, not tested, but it should help you to understand idea o two way binding in angular.
Here is my approach to this requirement. Let me know if any further improvement can be added. The entire code can be found at the below URL:
Angular Save, Update and Delete
The sample screenshots from the code can be found here...
controller:
'use strict';
function MainController($scope, SharedService, ngDialog) {
$scope.account_type_selected = "Savings";
$scope.sharedService = SharedService;
$scope.savingsMain = [];
$scope.checkingsMain = [];
$scope.addToCheckingsAccounts = {};
$scope.addToSavingsAccounts = {};
$scope.setAccountType = function (type) {
if (type === "allAccounts") {
$scope.showSavings = true;
$scope.showCheckings = true;
} else if (type === "savingsAccounts") {
$scope.showSavings = true;
$scope.showCheckings = false;
} else if (type === "checkingAccounts") {
$scope.showSavings = false;
$scope.showCheckings = true;
}
$scope.account_type_selected = type;
};
$scope.$watch('savingsMain', function ($scope) {
return $scope.savingsMain;
});
$scope.selectedAccountType = function (showAccount) {
console.log(showAccount);
if (showAccount === "Savings") {
$scope.sharedService.accountType = "Savings";
} else {
$scope.sharedService.accountType = "Checkings";
}
};
$scope.saveAccounts = function () {
if ($scope.sharedService.accountType === "Savings") {
$scope.addToSavingsAccounts = {
"account_type": $scope.sharedService.accountType,
"amount": $scope.sharedService.amount,
"date": $scope.sharedService.date,
"maturity": $scope.sharedService.maturity
};
$scope.showSavings = true;
$scope.savingsMain.push($scope.addToSavingsAccounts);
} else {
$scope.addToCheckingsAccounts = {
"account_type": $scope.sharedService.accountType,
"amount": $scope.sharedService.amount,
"bic": $scope.sharedService.BIC,
"iban": $scope.sharedService.IBAN
};
$scope.showCheckings = true;
$scope.checkingsMain.push($scope.addToCheckingsAccounts);
}
ngDialog.close();
};
$scope.deleteDataFromSharedService = function (accountType, item) {
if (accountType === "Savings") {
$scope.savingsMain = _.without($scope.savingsMain, _.findWhere($scope.savingsMain, { date: item }));
} else if (accountType === "Checkings") {
$scope.checkingsMain = _.without($scope.checkingsMain, _.findWhere($scope.checkingsMain, { bic: item }));
}
};
$scope.closeDialog = function () {
ngDialog.close();
};
$scope.accountTypeModel = [];
$scope.prop = {
"type": "select",
"name": "account_type",
"value": $scope.sharedService.accountType,
"accountTypeData": ["Savings", "Checkings"]
};
}
<form ng-controller="MainController">
<div class="page-header">
<h1>Angular-Save-Update-Delete</h1>
</div>
<div class="content-wrapper">
<div class="sidebar">
<table>
<tbody>
<tr>
<td>
<button ng-click="setAccountType('allAccounts')" ng-model="allAccounts" class="ng-pristine ng-untouched ng-valid ng-empty">All</button>
</td>
</tr>
<tr>
<td>
<button ng-click="setAccountType('savingsAccounts')" ng-model="savingsMain" class="ng-pristine ng-valid ng-not-empty ng-touched">Savings</button>
</td>
</tr>
<tr>
<td>
<button ng-click="setAccountType('checkingAccounts')" ng-model="checkingsMain" class="ng-pristine ng-untouched ng-valid ng-not-empty">Checkings</button>
</td>
</tr>
<tr>
<td>
<button class="create-account-btn-class"
type="button"
ng-dialog="app/views/create-account-template.html"
ng-dialog-data=""
ng-dialog-class="ngdialog-theme-default"
ng-dialog-scope="this"
plain=false
showClose=true
closeByDocument=true
closeByEscape=true
ng-dialog-show-close="false">New Account</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="right-content">
<div id="savingsTemplate" templateurl="app/views/savings.html" ng-show="showSavings" include-template=""></div>
<div id="checkingsTemplate" templateurl="app/views/checkings.html" ng-show="showCheckings" include-template=""></div>
</div>
</div>
</form>

Factory not providing proper values to controller

In my angular js project factory is not providing values to the controller as needed. I always get empty result in view. When i logged in browser using console.log() all i can see in console is :
[object Object],[object Object],[object Object]. I am stuck at this. Tried many things but nothing worked.
This is my controller code:
var controllers = {};
controllers.ProductController = function ($scope, $route, $routeParams, $location, ProductFactory) {
$scope.products = [];
var init = function () {
$scope.products = ProductFactory.getProducts();
console.log('got products in controller');
console.log($scope.products)
};
var initProductEdit = function () {
var code = $routeParams.code;
if (code = undefined) {
$scope.currentProduct = {};
}
else
{
$scope.currentProduct = ProductFactory.loadProductByCode(code);
}
};
$scope.$on('$viewContentLoaded', function () {
var templateUrl = $route.current.templateUrl;
if (templateUrl == '/Partials/ProductEdit.html') {
initProductEdit();
}
else if (templateUrl == '/Partials/ProductList.html')
{
var code = $routeParams.code;
if(code!=undefined)
{
$scope.deleteProduct(code);
}
}
});
init();
$scope.saveProduct = function () {
ProductFactory.saveProduct($scope.currentProduct);
$location.search('code', null);
$location.path('/');
};
$scope.deleteProduct = function (code) {
ProductFactory.deleteProduct(code);
$location.search('code', null);
$location.path('/');
};
};
angSPA.controller(controllers);
This is my factory code:
angSPA.factory('ProductFactory', function () {
var products = [
{ code: 1, name: 'Game of Thrones', description: 'Series' }
{ code: 2, name: 'DmC', description: 'Game' },
{ code: 3, name: 'Matrix', description: 'Movie' },
{ code: 4, name: 'Linkin Park', description: 'Music Band' }];
var factory = {};
console.log('initializing factory');
factory.getProducts = function () {
console.log('factory now providing products');
return products;
};
factory.loadProductByCode = function (code) {
var product;
for (var i = 0; i < products.length; i++) {
if (products[i].code == code) {
product = products[i];
return product;
}
}
};
factory.saveProduct = function (product) {
products.push(product);
console.log('factory saved product');
};
factory.deleteProduct = function (code) {
var product = factory.loadProductByCode(code);
if (product != null) {
products.remove(product);
console.log('factory deleted product');
}
};
console.log('returning factory');
return factory;
});
This is my view:
<div class="container">
<h2 class="page-title">Product Listing</h2>
<div class="searchbar">
<ul class="entity-tabular-fields">
<li>
<label>Search: </label>
<span class="field-control">
<input type="text" data-ng-model="filter.productName" />
</span>
<label></label>
</li>
</ul>
</div>
<h2>Add New Product</h2>
<table class="items-listing">
<thead>
<tr>
<th>Code</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td data-ng-repeat="product in products|filter:filter.productName"></td>
<td>{{product.code}}</td>
<td>{{product.name}}</td>
<td>{{product.description}}</td>
<td>Delete</td>
</tr>
</tbody>
</table>
</div>
My routing function:
angSPA.config(function ($routeProvider) {
$routeProvider
.when(
'/',
{
controller: 'ProductController',
templateUrl: 'Partials/ProductList.html'
})
.when(
'/ProductEdit',
{
controller: 'ProductController',
templateUrl: 'Partials/ProductEdit.html'
})
.otherwise({
redirectTo: '/'
});
console.log('routing done');
});
Change your htmt given
var angSPA = angular.module('angSPA', []);
angSPA.controller("ProductController", function($scope, ProductFactory) {
$scope.products = [];
var init = function() {
$scope.products = ProductFactory.getProducts();
console.log('got products in controller');
console.log($scope.products + "")
};
init();
});
angSPA.factory('ProductFactory', function() {
var products = [
{code: 1, name: 'Game of Thrones', description: 'Series'},
{code: 2, name: 'DmC', description: 'Game'},
{code: 3, name: 'Matrix', description: 'Movie'},
{code: 4, name: 'Linkin Park', description: 'Music Band'}];
var factory = {};
console.log('initializing factory');
factory.getProducts = function() {
console.log('factory now providing products');
return products;
};
factory.loadProductByCode = function(code) {
var product;
for (var i = 0; i < products.length; i++) {
if (products[i].code == code) {
product = products[i];
return product;
}
}
};
factory.saveProduct = function(product) {
products.push(product);
console.log('factory saved product');
};
factory.deleteProduct = function(code) {
var product = factory.loadProductByCode(code);
if (product != null) {
products.remove(product);
console.log('factory deleted product');
}
};
console.log('returning factory');
return factory;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<body ng-app="angSPA" ng-controller="ProductController">
<div class="container">
<h2 class="page-title">Product Listing</h2>
<div class="searchbar">
<ul class="entity-tabular-fields">
<li>
<label>Search: </label>
<span class="field-control">
<input type="text" data-ng-model="filter.productName" />
</span>
<label></label>
</li>
</ul>
</div>
<h2>Add New Product</h2>
<table class="items-listing">
<thead>
<tr>
<th>Code</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="prod in products|filter:filter.productName">
<td ></td>
<td>{{prod.code}}</td>
<td>{{prod.name}}</td>
<td>{{prod.description}}</td>
<td>Delete</td>
</tr>
</tbody>
</table>
</div>
Your ng-repeat directive should be on the tr element and not the td.
<tr data-ng-repeat="product in products|filter:filter.productName">
Not the cause of your problem, but to log in a service or controller, you can use the $log service and stringify to serialize your objects.
$log.debug(JSON.stringify($scope.products));
Looking at your code, you do $scope.products = [] right at the beginning. This will make angular watch the empty array.
In your init function you assign the products array to $scope.products. But as angular is still watching the initial array it will not be aware of the change.
The solution is to delete the initial assignment $scope.products = [] and make sure to alter the original array but never set it to a new array.
BTW: you could do console.log(JSON.stringify($scope.products)) to get better log information.

how to move filter outside of controller in angular

I'm new in angular . i managed to filter using angular and it work fine but now i want to move filter outside of the controller which is quite challenging for me .
here is my html page :
<div >
<input type="checkbox" ng-click="itemType('CAR')"/> CAR
<input type="checkbox" ng-click="itemType('BIKE')"/> BIKE
<input type="checkbox" ng-click="itemType('CYCLE')"/> CYCLE
</div>
<table>
<tbody>
<tr ng-repeat="item in items | filter:filterItem">
<td >{{item.name}}</td>
<td >{{item.type}}</td>
</tr>
</tbody>
</table>
and controller :
app.controller('MainCtrl', function($scope) {
$scope.items = [
{name: 'bmw', type:'CAR' },
{name: 'ducati',type:'BIKE'},
{name: 'airbas',type:'CYCLE' }
];
$scope.typeArray = [];
$scope.itemType = function(type) {
var i = $.inArray(type, $scope.typeArray);
if (i > -1) {
$scope.typeArray.splice(i, 1);
} else {
$scope.typeArray.push(type);
}
}
$scope.filterItem = function(item) {
if ($scope.typeArray.length > 0) {
if ($.inArray(item.type, $scope.typeArray) < 0){
return false;
}
}
return item;
}
});
how can i move filtering from controller to app.filter().
Thanks.
Yes, the custom filter is a separate module and you can write it as:
iApp.filter('myfilter', function() {
return function( items, types) {
var filtered = [];
var looping = function(name){
angular.forEach(items, function(item) {
if(item.type === name){
filtered.push(item);
}
});
}
if(types.car == true){
looping('CAR');
}
if(types.bike == true){
looping('BIKE');
}
if(types.cycle == true){
looping('CYCLE');
}
return filtered;
};
});
Controller:
$scope.types = {car: false, bike:false, cycle: false};
$scope.items = [
{name: 'bmw', type:'CAR' },
{name: 'ducati',type:'BIKE'},
{name: 'airbas',type:'CYCLE' }
];
Demo 1 Plunker
[EDIT]
If you want to show all cells when no checkbox is selected, add this to filter:
var flag = true;
angular.forEach(types, function(type){
flag = flag & !type; // if one of flags will be false, we get flag=false
});
if(flag == true){
return items;
}
Demo 2 Plunker
FYI: You can see that filters do not use $scope. If you want to pass additional argument the syntax should be:
<tr ng-repeat="item in items | filter:myfilter:types">
where types is some object

Resources