Array Push not working with Real Time - angularjs

I'm using Pusher for Angular Webapp for Real Time Application. I need add to array products a new item when other add a item from form in other session. In my sessiĆ³n it's works. In another session the data obtained if it is added to the array but not shown in the ng-repeat.
Controller:
.controller('MainCtrl', ['$scope','Products',function($scope,Products) {
$scope.products = Products.getAll();
var pusher = new Pusher('MY KEY', {
encrypted: true
});
$scope.addProduct = function(product){
Products.addProduct(product);
}
var callback = function(data) {
$scope.products.push(data.NewProduct);
console.log($scope.products);
};
var channel = pusher.subscribe('products');
channel.bind('addProduct', callback);
}]);
View:
<tbody>
<tr ng-repeat="product in products track by product.id">
<td >{{product.name}}</td>
<td>{{product.unity}}</td>
<td>{{product.price}}</td>
<td>
<button>
Edit
</button>
<button>
Delete
</button>
</td>
</tr>
</tbody>

$evalAsync Executes the expression on the current scope at a later point in time.
So add $evalAsync to callback function in your code
.controller('MainCtrl', ['$scope','$evalAsync','Products',function($scope,$evalAsync, Products) {
$scope.products = Products.getAll();
var pusher = new Pusher('MY KEY', {
encrypted: true
});
$scope.addProduct = function(product){
Products.addProduct(product);
}
var callback = function(data) {
$scope.products.push(data.NewProduct);
console.log($scope.products);
};
var channel = pusher.subscribe('products');
channel.bind('addProduct', $evalAsync(callback));
}]);

I did it like this:
var callback = function(data) {
$scope.$apply(function(){
$scope.products.push(data.Producto);
});
console.log($scope.products);
};

Related

AngularJS ng-click not responding when clicked

I know there is alot of questions about this topic out there, but could not find any solution to my problem. My code:
UPDATE
$scope.openOne = function (id) {
ImageService.getDetails(id).then(function (data) {
$scope.imageDetail = data;
}).catch(function (e) {
var message = [];
});
}
function getAllImages() {
ImageService.getImages().then(function (value) {
$scope.images = value;
var items = [];
$(value).each(function () {
var url = "https://someUrl/" + this.Image[0];
console.log(url);
items.push(`
<tr>
<td><button id="button" ng-click="openOne(${this._id})">${this.ImageName}</button></td>
<td>${this.ImageCategory}</td>
<td>
<img style="width:30%;" ng-src="${url}" alt="The Image is missing">
</td>
</tr>
`);
});
$("#body").append(items.join(''));
}).catch(function (e) {
var message = [];
}).finally(function (e) {
});
}
I am creating the button in in the controller and then appending it to the DOM.
Does anybody see the error? When I click the button nothing happens.
Approach is all wrong.
The fundamental principal in angular is let your data model drive the view and let angular compile that view from templates
A more typical set up would pass your images array to ng-repeat in the view:
Controller:
function getAllImages() {
ImageService.getImages().then(function (value) {
$scope.images = value;
});
}
View:
<tr ng-repeat="img in images track by $index">
<td><button id="button" ng-click="openOne(img.id)">{{img.ImageName}}</button></td>
<td>{{img.ImageCategory}}</td>
<td>
<img style="width:30%;" ng-src="{{img.url}}" alt="The Image is missing">
</td>
</tr>
You need to add $compile service here, that will bind the angular directives like ng-click to your controller scope. For example
app.controller('yourController', function($scope,$compile) {
var button = '<button id="button" ng-click="openOne(${this._id})">${this.ImageName}</button>';
items.push(button);
$("#body").append(items.join(''));
var temp = $compile(button)($scope);
$scope.openOne = function(){
alert('Yes Click working at dynamically added element');
}
});

$scope variable is undefined in post

I have AngularJS repeat biaya in data_biaya that I have from JSON.
When I ng-click="simpan_biaya(data_biaya)", why is the data posting undefined?
<input type="button" ng-click="simpan_biaya(data_biaya)" value="Simpan"/>
<tr ng-repeat="biaya in data_biaya | filter:{tahapan_id : 10}" >
<td>{{$index+1}}</td>
<td><span >{{biaya.tanggal_transaksi}}</span></td>
<td><span>{{biaya.uraian}}</span></td>
<td><span>{{biaya.pihak_nama}}</span></td>
<td><span >{{data_biaya[$index].pemasukan}}</span></td>
<td><span>{{biaya.pengeluaran}}</span></td>
<td>{{biaya.sisa}}</td>
<td><span >{{biaya.keterangan}}</span></td>
</tr>
JavaScript
var datanya=[
{"id":"23713","id_pembiayaan":"1","perkara_id":"7200","tahapan_id":"10","kategori_id":"1","jenis_biaya_id":"1","pihak_id":null,"pihak_ke":null,"urutan":"1","jenis_transaksi":"1","tanggal_transaksi":"2016-05-26","uraian":"Panjar Biaya Perkara","pemasukan":1000000,"pengeluaran":0,"jumlah":1000000,"sisa":1000000,"keterangan":null,"pihak_nama":"Penggugat"},
{"id":"23714","id_pembiayaan":"1","perkara_id":"7200","tahapan_id":"10","kategori_id":"11","jenis_biaya_id":"61","pihak_id":null,"pihak_ke":null,"urutan":"2","jenis_transaksi":"-1","tanggal_transaksi":"2016-05-26","uraian":"Biaya Pendaftaran\/PNBP","pemasukan":0,"pengeluaran":"30000.00","jumlah":"30000.00","sisa":970000,"keterangan":null,"pihak_nama":"Penggugat"}
];
var app = angular.module('jurnalApp', []);
app.controller('jurnalCtrl', function($scope,$http) {
$scope.data_biaya = [];
$scope.searchClick = function (data) {
$scope.$apply(function(){
$scope.data_biaya=datanya;
});
};
$scope.simpan_biaya = function(data){
var post_data = data;
$.post("<?php echo base_url().'all_jurnal/set_jurnal_biaya';?>", post_data)
.done(function(json){
});
}
angular.element(document).ready(function () {
$scope.searchClick();
});
});
Here: plunker
Try this:
<input type="button" ng-click="simpan_biaya(data_biaya)" value="Simpan"/>
DEMO
Based on the attached screenshot, you should pass JSON data, convert the data to JSON before passing:
var dataJson=angular.toJson(post_data);
you should use that:
var post_data = data; var dataJson=angular.toJson(post_data); $.post("
<?php echo base_url().'all_jurnal/set_jurnal_biaya';?>", dataJson ) .done(function(json){ });

angularjs not updaing propeties when promises used

I am using service to get JSON object using promises. It is then converted into array and assign to a property which is in $scope object. The problem is that array is not getting updated or any properties inside promise then() method.
Controller
var searchController = function ($scope, $SPJSOMService) {
$scope.myName = "old name";
$scope.getUsers = function ($event) { //called on button click
$event.preventDefault();
var queryText = "test user";
$SPJSOMService.getUsers(queryText)
.then(function myfunction(users) {
$scope.userCollection = JSON.parse(JSON.stringify(users)).d.results;
// $scope.$apply(); this line throwing error. $rootScope in progress
$scope.myName = "new name"; //not getting updated
}, function (reason) {
alert(reason);
});
};
};
Service
var SPJSOMService = function ($q, $http, $rootScope) {
this.getUsers = function (userToSerach) {
var deferred = $q.defer();
$http({
url:'some url',
method: "GET",
headers: {
"accept": "application/json;odata=verbose",
"content-Type": "application/json;odata=verbose"
}
})
.success(function (data, status, headers, config) {
deferred.resolve(data); //successfully return data
})
.error(function (data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
};
};
Updated
index.html
<div ng-include="'Search.html'">
</div>
<div ng-include="'searchResults.html'"></div>
search.html
<div id="containerDiv" ng-controller="searchController as search">
<input class="button" type="button" ng-click="getUsers($event);" value="Search" id="btnSearch" />
</div>
searchResults.html
<div ng-controller="searchResultController as result">
<table >
<thead>
<tr>
<th>Name</th>
<th>EMail</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in userCollection">
<td>{{$index}} {{item.userName}}</td>
<td>{{$index}} {{item.userEmail}}</td>
</tr>
</tbody>
</table>
</div>
So search.html returns the data by calling the service and I am trying to pass it to the page namely searchResults.html which have its own controller.
$scope.users = $scope.userCollection;
Service class correctly returning data, but the problem is inside then(), which is not updating $scope.userCollection, hence UI is not getting updated.
Please help me out, what am I missing here.
In angular controllers can bind to the view in two ways:
"controller as"
through scope
It looks you are using the "controller as" flavor here...
<div ng-controller="searchResultController as result">
Refer to https://docs.angularjs.org/api/ng/directive/ngController for more information.
Change your controller code to:
var searchController = function ($scope, $SPJSOMService) {
//note use of "this" instead of "$Scope"
var _this = this;
_this.myName = "old name";
_this.getUsers = function ($event) { //called on button click
$event.preventDefault();
var queryText = "test user";
$SPJSOMService.getUsers(queryText)
.then(function myfunction(users) {
_this.userCollection = users.d.results; //You don't need JSON.parse not JSON.stringify
_this.myName = "new name";
}, function (reason) {
alert(reason);
});
};
};
and in your view use the controller "alias":
<div ng-controller="searchResultController as result">
...
<tr ng-repeat="item in result.userCollection">
...
You have to push it to the new array I think. Have you tried this in your then statement?
$scope.myName.push("new name");
It should put it in the existing array. Let me know if it works.

MEAN Stack: Count and show the Sum of Values via AngularJS

Hi I'm a beginner with the MEAN Stack and currently stuck with a logical challenge.
I know how to get the count of elements of my table with {{element.length}} in HTML but I need to get the total sum of a given value.
Thanks for your help in advance!
HTML:
<div class="jumbotron text-center">
<h1>Volume <span class="label label-info">{{getTotal()}} </span></h1>
</div>
<div class="text-center" >
<table class="table" >
<thead>
<tr>
<th>Drink</th>
<th>Volume</th>
<th>Date</th>
<th>Comment</th>
<th>Action</th>
</tr>
</thead>
<tbody ng-repeat="drink in drinks">
<tr>
<td>{{drink.text}}</td>
<td>{{drink.volume}} Liter</td>
<td>{{drink.time}}</td>
<td>{{drink.comment}}</td>
<td><button type="submit" class="btn btn-primary btn-sm"
ng-click="deleteDrink(drink._id)">delete</button></td>
</tr>
</tbody>
</table>
</div>'
Model:
var mongoose = require('mongoose');
var Schema =new mongoose.Schema({
text : {type : String, default: ''},
volume: {type: Number, default: null},
zeit: {type: Date, default:Date.now},
comment: {type: String}
});
module.exports = mongoose.model('mongoose', Schema);'
Controller:
angular.module('drinkController', [])
// inject the drink service factory into our controller
.controller('mainController', ['$scope','$http','Drinks', function($scope, $http, Drinks) {
$scope.formData = {};
$scope.loading = true;
// GET =====================================================================
// when landing on the page, get all drinks and show them
// use the service to get all the drinks
Drinks.get()
.success(function(data) {
$scope.drinks = data;
$scope.loading = false;
});
// CREATE ==================================================================
// when submitting the add form, send the text to the node API
$scope.createDrink = function() {
// validate the formData to make sure that something is there
// if form is empty, nothing will happen
if ($scope.formData.text != undefined) {
$scope.loading = true;
// call the create function from our service (returns a promise object)
Drinks.create($scope.formData)
// if successful creation, call our get function to get all the new drinks
.success(function(data) {
$scope.loading = false;
$scope.formData = {}; // clear the form so our user is ready to enter another
$scope.drinks = data; // assign our new list of drinks
});
}
}
//Problem Function!! I don't know how to read desired values
$scope.getTotal=function(){
var total=0;
for (var i=0; i <$scope.drinks; i++){
var sum= $scope.drinks.volume[i]; //??
total= sum ; //?
}
return total;
}
// DELETE ==================================================================
// delete a todo after checking it
$scope.deleteDrink = function(id) {
$scope.loading = true;
Drinks.delete(id)
// if successful creation, call our get function to get all the new todos
.success(function(data) {
$scope.loading = false;
$scope.drinks = data; // assign our new list of todos
});
};
}]);
So I have at /api/drinks
[{"_id":"555c23943e0bf3fc403864c3",
"comment":"Yummie",
"__v":0,
"time":"2015-05-20T06:03:17.340Z",
"**volume":2**,
"text":"Coke"},
{"_id":"555c239d3e0bf3fc403864c4",
"comment":"Mooh!",
"__v":0,
"time":"2015-05-20T06:03:17.340Z",
**"volume"**:1,
"text":"Milk"}
]
In my HTML I need a Display of the Value of all Volume Entries, so it would be 3.
This should work:
$scope.getTotal=function(){
var total=0;
for (var i=0; i <$scope.drinks.length; i++){
total += $scope.drinks[i].volume;
}
return total;
}

why is this resource not updating the view after using $delete method

In my angular app I have a controller as follows:
function TemplateListControl($scope, TemplateService){
$scope.templates = TemplateService.get(); // Get objects from resource
// Delete Method
$scope.deleteTemplate = function(id){
$scope.templates.$delete({id: id});
}
}
Within the view I have a table thats bound to templates model. as follows:
<table ng-model="templates">
<thead>
<tr>
<th style="width:40%">Title</th>
<th style="width:40%">controls</th>
</tr>
<thead>
<tbody>
<tr ng-repeat="template in templates">
<td>
<!-- Link to template details page -->
<a href="#/template/[[template.id]]">
[[template.title]]
</a>
</td>
<td>
<!-- Link to template details page -->
<a class="btn btn-primary btn-small"
href="#/template/[[template.id]]">Edit
</a>
<!-- Link to delete this template -->
<a class="btn btn-primary btn-small"
ng-click="deleteTemplate(template.id)">Delete
</a>
</td>
</tr>
</tbody>
</table>
Now when I click on the delete link in the above template, It calls the deleteTemplate method and a successful DELETE call is made to the REST api. But the view does not get updated until it is refreshed and $scope.templates = TemplateService.get(); is initiated again. What am I doing wrong?
I prefer using promises instead of callback. Promises are the new way to handle asynchronous processes. You can inspect the result using a a promise right after it came back from the server.
//Controller
myApp.controller('MyController',
function MyController($scope, $log, myDataService) {
$scope.entities = myDataService.getAll();
$scope.removeEntity = function (entity) {
var promise = myDataService.deleteEntity(entity.id);
promise.then(
// success
function (response) {
$log.info(response);
if (response.status == true) {
$scope.entities.pop(entity);
}
},
// fail
function (response) {
$log.info(response);
// other logic goes here
}
);
};
});
//DataService
myApp.factory('myDataService', function ($log, $q, $resource) {
return {
getAll: function () {
var deferred = $q.defer();
$resource('/api/EntityController').query(
function (meetings) {
deferred.resolve(meetings);
},
function (response) {
deferred.reject(response);
});
return deferred.promise;
},
deleteEntity: function (entityId) {
var deferred = $q.defer();
$resource('/api/EntityController').delete({ id: entityId},
function (response) {
deferred.resolve(response);
},
function (response) {
deferred.reject(response);
});
return deferred.promise;
}
};
});
//Web API Controller
public class MeetingController : BaseApiController
{
// .... code omited
public OperationStatus Delete(int entityId)
{
return _repository.Delete(_repository.Single<MyEntity>(e => e.EntityID == entityId));
}
}
Note: $log, $q, $resource are built in services. Hope it helps :)
You also have to update client side so modify your source code as below
ng-click="deleteTemplate($index)">
$scope.delete = function ( idx ) {
var templateid = $scope.templates[idx];
API.Deletetemplate({ id: templateid.id }, function (success) {
$scope.templates.splice(idx, 1);
});
};
You could pass a callback function to $resource.$delete
function TemplateListControl($scope, TemplateService){
$scope.templates = TemplateService.get(); // Get objects from resource
// Delete Method
$scope.deleteTemplate = function(id){
TemplateService.$delete({id: id}, function(data) {
$scope.templates = data;
});
}
}
Attention
If your REST APIs delete function returns an array you have to set isArray: true in your Angular $resource to avoid a AngularJS $resource error - TypeError: Object # has no method 'push'
$resource(URL, {}, {
delete: {method:'DELETE', isArray: true}
});

Resources