I am using AngularJS and to show products in a table to my users. Here the user can filter the table using categories or other key words. But the user has to be able to edit the product table, like editing product names or prices and these data has to be altered also in my database of course. Now I am using xeditable which works great and I am able to get the productID which I have to change and the function to change the data gets called but that's it. Here can you see my code:
AngularJS
categorieFilter = angular.module("categorieFilter", ["xeditable"])
categorieFilter.run(function(editableOptions) {
editableOptions.theme = 'bs3'; // bootstrap3 theme. Can be also 'bs2', 'default'
});
categorieFilter.controller("catFilter", ["$scope", "store", function($scope, store){
$scope.search = "";
$scope.products = [];
$scope.categories = [];
$scope.postname = function ($prodid){
$http.get('api/editproduct/id/$scope.product.name')
.success(function(results){
})
.error(function(data, status){
console.error("Category add error: ", status, data);
});
};
store.getCategories().then(function(data){
$scope.categories = data;
})
store.getProducts().then(function(data){
$scope.products = data;
})
$scope.filterProductsByCats = function(category){
$scope.search = category;
};
}])
categorieFilter.factory('store', function($http, $q){
function _getCategory (){
var deferred = $q.defer();
$http.get('api/categories').success(function (data) {
deferred.resolve(data);
})
return deferred.promise;
}
function _getProducts (){
var deferred = $q.defer();
var prods = [];
$http.get('api/products').success(function (data) {
for(var i = 0;i<data.length;i++)
{
prods[i] = {id: data[i][0], name: data[i][1], category: data[i][3], price: data[i][2]};
}
deferred.resolve(prods);
})
return deferred.promise;
}
return {
getCategories: _getCategory,
getProducts : _getProducts
};
});
HTML
<div ng-app="categorieFilter" ng-cloak="" ng-controller="catFilter">
<div class="input-group">
<input type="text" name="table_search" class="form-control input-sm pull-right" ng-model="search" placeholder="Search"/>
<div class="input-group-btn">
<button class="btn btn-sm btn-default">
<i class="fa fa-search"></i>
</button>
</div>
</div>
<div>
<input type="submit" class="btn btn-success" style="margin:10px; width:30%;" ng-repeat="cat in categories" ng-click="filterProductsByCats(cat.categoryName)" value="{{cat.categoryName}}">
</div>
<table class="table table-hover">
<tr style="background-color:#ddd;">
<th colspan="4" style="text-align:left; font-size:16px;"> Category </th>
<th colspan="4" style="text-align:left; font-size:16px;"> Product </th>
<th colspan="4" style="text-align:left; font-size:16px;"> Price </th>
</tr>
<tr ng-repeat="product in products | filter:search | orderBy: 'category'">
<td colspan="4">{{product.category}}</td>
<td colspan="4" onaftersave="postname(product.id)" editable-text="product.name">{{product.name}}</td>
<td colspan="4" editable-text="product.price">{{product.price}}</td>
</tr>
</table>
I(m getting error:
ReferenceError: $http is not defined
So what am I doing wrong here? How can I update the required data in my database after changing it in my table using angular and xeditable..?
I updated my controller and function like this and now it works fine:
categorieFilter.controller("catFilter", ["$scope", "$http", "store", function($scope, $http, store){
$scope.search = "";
$scope.products = [];
$scope.categories = [];
$scope.postname = function ($prodid, $prodname){
alert($prodname);
$http.get('api/editproduct/'+$prodid+'/'+$prodname)
.success(function(results){
})
.error(function(data, status){
console.error("Category add error: ", status, data);
});
};
Related
When the below form is submitted, and additional entry is created into the database. But the ng-repeat is not getting refreshed.
Any ideas?
html code:
<table class="redTable">
<thead>
<tr>
<th> Domain</th>
<th> Username</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="eachuserconfigdata in userconfigdata track by $index">
<td>
<input type="text" ng-model="eachuserconfigdata.Domain" value="{{ eachuserconfigdata.Domain }}" ng-readonly='!($index == eEditable)' ng-dblclick="eEditable = $index" style="background-color: transparent ; width:80px;border: 0;" />
</td>
<td>
<input type="text" ng-model="eachuserconfigdata.UserName" value="{{ eachuserconfigdata.UserName }}" ng-readonly='!($index == eEditable)' ng-dblclick="eEditable = $index" style="background-color: transparent ; width:80px;border: 0;" />
</td>
</tr>
</tbody>
</table>
<br />
</div>
Javascript
var myApp = angular.module("mymodule", ['ngMaterial']);
var myController = function ($scope, $http, $log) {
$scope.username = "";
$scope.ps = "";
$scope.submit = function () {
//alert($scope.username);
//alert($scope.ps);
$scope.myStyle = { color: 'red' };
var data = {
Domain: $scope.domainname,
UserName: $scope.domainusername,
Password: $scope.domainps
};
$http({
method: 'POST',
//url: 'Login/LoginUser?user=' + $scope.username + '&password=' + $scope.ps,
url: 'Login/UpdateDomainConfiguration',
data: data,
headers: { "Content-Type": "application/json" }
})
.then(function successCallback(response) {
var userid = 0;
$scope.message = response.data;
//$log.info(response);
$scope.GetUserConfigDetails();
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
alert(response.data);
});
}
What you did based on your code is you just saved it to db but never fetched it (not sure about this $scope.GetUserConfigDetails(); though).
What you need to do is after saving it to db, fetch the data again and assign it to your ng-repeat array. Or you can just simply insert the data you've saved to the db into your existing array so that you don't have to fetch again.
ANGULAR JS
var App = angular.module('myApp', [])
App.controller('mainController', function ($scope, $http) {
$http.get("/Project/getProjects")
.success(function (result) {
$scope.SuccMsg = "SUCCESS.. ";
$scope.projectList = result;
})
.error(function (Data) {
$scope.ErrMsg = "ERROR.. " + Error;
}) })
CONRTOLLER : PROJECT
public JsonResult getProjects()
{
List<Project> p2 = new List<Project>();
p2 = db.Projects.ToList();
return Json(p2,JsonRequestBehavior.AllowGet);
}
HTML FILE
Project
<div ng-controller="mainController">
#*LIST PROJECT*#
<table id="tbl_Project" class="table-striped">
<tr ng-repeat="item in projectList">
<td>{{item.p_name}}</td>
<td>#*DELETE PROJECT*#
<input id="btn_delete" ng-click="deleteProject(item)" value="X" type="button" />
</td>
</tr>
</table>
<br /><br />
<div style="color:firebrick"><b>{{ErrMsg}}</b></div>
<div style="color:forestgreen"><b>{{SuccMsg}}</b></div> </div>
I have looked at a number of other questions related to this such as
AngularJS : ng-repeat list is not updated when a model element is spliced from the model array
ng-repeat not updating on update of array
However I think that the way I built my app is sufficiently different that these aren't helping me.
I think my idea of doing this:
$rootScope.$on('connectionDispositionChanged',function(event, item){
$scope.data.matches[item.index].info.disposition = item.disposition;
});
Isn't really working out the way I had hoped. I can actually see in the console that this updating, but it doesn't update in the table. Adding $scope.$apply() after this causes a digest in-progress error.
show.phtml
<div class="container-fluid" ng-app="analysisApp" ng-controller="analysisController">
<table class="table table-condensed">
<thead>
<tr >
<th ng-repeat="header in baseColumns" class="text-center">{{header.name | tableHeader}}</th>
<th ng-repeat="header in comparisonColumns" class="text-center text-info">{{header.name | tableHeader}}</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr table-row data="data" ng-repeat="item in data.matches | filter:searchMatchText track by $index">
</tbody>
</table>
<row class="col-md-12 text-center"><span class="text-muted">End of Data</span></row>
</div><!-- #matches -->
</div>
tableRowDirective.js
"use strict";
analysisApp.directive("tableRow", function($compile) {
var getTemplate = function(scope, element, attrs){
var base = scope.item.base;
var comp = scope.item.comparison;
var info = scope.item.info;
// other non-relevant code...
returnString += '<td class="text-center"><button class="btn btn-default btn-xs" ng-click="matchesSetDisposition(item, data.settings, $index)" >Set Disposition</button>';
returnString += '</td>';
return returnString;
};
var linker = function(scope, element, attrs){
element.html(getTemplate(scope, element, attrs));
$compile(element.contents())(scope);
};
return {
restrict : "A",
replace : true,
link: linker
};
});
analysisController.js
"use strict";
analysisApp.controller('analysisController', ['$scope','$rootScope','loadData','saveData','$uibModal', function ($scope, $rootScope, loadData, saveData, $uibModal, $log) {
$rootScope.$on('connectionDispositionChanged',function(event, item){
// $scope.data.matches[item.index].info.disposition = item.disposition;
});
$scope.matchesSetDisposition = function(item, scope, index){
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: '/angular/analysis/templates/matches-modal.html',
controller: 'matchesModalController',
size: 'lg',
resolve: {
itemData: function () {
return {
dispositionLabels: $scope.dispositionLabels,
disposition: item.info.disposition,
connectionID: item.info.id,
comparisonID: comparisonID,
baseItemID: item.base.id,
baseTitle: itemTitle(item.base),
comparisonItemID: item.comparison.id,
comparisonTitle: itemTitle(item.comparison),
index: index
}
}
}
});
modalInstance.result.then(function (item) {
$scope.data.matches[item.index].info.disposition = item.disposition;
saveTheData('/analysis/apisaveconnectiondisposition', item);
}, function () {
});
};
}]);
matchesModalController.js
"use strict";
analysisApp.controller('matchesModalController', function ($scope, $rootScope, $uibModalInstance, itemData, saveData) {
$scope.itemData = itemData;
$scope.ok = function (item) {
$uibModalInstance.close(item);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
$scope.delink = function (item) {
BootstrapDialog.confirm({
title: 'WARNING',
message: '<p>Are you sure that you want to break the link between these items?</p>',
type: BootstrapDialog.TYPE_DANGER,
btnOKLabel: 'Break the link',
btnOKClass: 'btn-danger',
callback: function(result) {
if(result) {
$uibModalInstance.dismiss('delink');
saveTheData('/analysis/apidelink', item);
}else {
// cancel the operation
}
}
});
};
var saveTheData = function(url, item){
saveData
.postData(url, item)
.then(function(dataResponse){
$rootScope.$broadcast('connectionDispositionChanged', item);
})
};
});
I want to render a table adding row per each objects in an array.
I got a Controller like:
app.controller('SignUpController',function ($scope, $http) {
var that = this
that.users = []
that.queryUsers = function() {
console.log("I'm being triggered")
$http.get("/existingUsers").
success(function (data,status,headers,config) {
console.log(data)
that.users = data
console.log(that.users)
}).
error(function (data,status, headers, config) {
console.log(status)
})
}
})
And the table markup:
<table class="table table-bordered">
<th ng-repeat="th in ['mail','Administrador','Miembro desde']">{{th}}</th>
<tr ng-repeat="p in signup.users">
<td>{{p._id}}</td>
<td>{{p.mail}}</td>
<td>{{p.admin}}</td>
</tr>
</table>
Ttable is within a div with ng-controller="SignUpController as signup". When I click a button I trigger queryUsers actually seein results in browser console:
[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
Both mail and _id are existing attributes per each object.
So the AJAX is being done and the array I should be iterating and rendering to HTML rows actually exists and is populated, but no rows are shown.
Why?
Edit
I tried not modifying the scope:
app.controller('SignUpController', function ($scope,$http) {
$scope.users = []
$scope.queryUsers = function() {
console.log("I'm being triggered")
$http.get("/existingUsers").
success(function (data,status,headers,config) {
console.log(data)
$scope.users = data
console.log($scope.users)
}).
error(function (data,status, headers, config) {
console.log(status)
})
}
})
<div class="tab-pane" id="usecase11" ng-controller="SignUpController">
<h3>Colaboradores</h3>
<div class="row">
<div class="col-sm-6">
<table class="table table-bordered">
<th ng-repeat="th in ['mail','Administrador','Miembro desde']">{{th}}</th>
<tr ng-repeat="p in users">
<td>{{p._id}}</td>
<td>{{p.mail}}</td>
<td>{{p.admin}}</td>
<td style="border:none;"><a class="close" ng-click="">$</a></td>
<td style="border:none;"><a class="close" ng-click="">*</a></td>
</tr>
</table>
</div>
</div>
</div>
However, again I can see such array printed at browser console but nothing rendered to HTML
Here is the evidence that queryUsers is being called and that $scope.users is getting something after it.
Something interesting is that I got: {{users}} right after the table and it's displaying an empty array.
Just in case this is the GET handling server code:
app.get('/existingUsers',function (request, response) {
membersCollection.find({},{"password":0}, function (err, data) {
if (err) response.send(404)
else {
data.toArray(function (err, docs) {
if (err) {
console.log(error)
response.send("Error")
}
response.send(JSON.stringify(docs, null, 4))
})
}
})
}
You don't modify the $scope. Here is the corrected code:
app.controller('SignUpController',function ($scope, $http) {
$scope.users = []
$scope.queryUsers = function() {
console.log("I'm being triggered")
$http.get("/existingUsers").
success(function (data,status,headers,config) {
console.log(data)
$scope.users = data
console.log($scope.users)
}).
error(function (data,status, headers, config) {
console.log(status)
})
}
})
HTML:
<table class="table table-bordered">
<th ng-repeat="th in ['mail','Administrador','Miembro desde']">{{th}}</th>
<tr ng-repeat="p in users">
<td>{{p._id}}</td>
<td>{{p.mail}}</td>
<td>{{p.admin}}</td>
</tr>
</table>
I have an API returning the following simple JSON array:
[
"efd98ad-first_key",
"100eb0a-second_key"
]
I am trying to render this as a table with Angular:
<div name="listkeys" class="container">
<div class="starter-template">
<div ng-bind-html="message"></div>
<table class="table table-striped table-bordered table-condensed sortable" ng-init="getKeys()">
<tr>
<th>bucket</th>
</tr>
<tr ng-repeat="bucket in buckets">
<td>{{bucket}}</td>
</tr>
</table>
</div>
</div>
JS:
var app = angular.module('flipDaSwitch', ['ngSanitize']);
app.controller('ListKeys', function($scope, $http) {
$scope.getKeys = function() {
$http.get('/api/keys').
success(function (data) {
$scope.response = data;
}).
error(function (data){
$scope.response = {}
});
};
});
It does not do anything but throwing an "Uncaught object" error and that is it.
How could I debug why it is failing?
You are storing the values in $scope.response, but you are using $scope.bucket at the ng-repeat:
$scope.getKeys = function() {
$http.get('/api/keys').
success(function (data) {
$scope.buckets= data;
}).
error(function (data){
$scope.buckets= {}
});
};
It looks like you do not have a scope item called buckets. I'd expect to see:
$scope.buckets = data
Inside the success callback.