Update property of object in callback function of Angular component - angularjs

I want to create a new Angular compontent, which should change the status of an object/model and then call the defined callback function.
The code looks like this:
HTML
<status-circle status="obj.status" on-update="save(obj)"></status-circle>
statusCirlcle.js
angular.module('app').component('statusCircle', {
templateUrl: '/views/components/statusCircle.html',
bindings: {
status: '=',
onUpdate: '&'
},
controller: function () {
this.update = function (status) {
if(this.status !== status) {
this.status = status;
this.onUpdate();
}
};
}
});
The property will be updated correctly (two-way binding works) and the save callback function gets called, BUT the object has the old status property set.
My question: How can I update the object in the callback function?
JSFiddle: https://jsfiddle.net/h26qv49j/2/

It looks like in statusCircle.js you should change
this.onUpdate();
to
this.onUpdate({status: status});
and then in the HTML change
<status-circle status="obj.status" on-update="save(obj)"></status-circle>
To
<status-circle status="obj.status" on-update="save(status)"></status-circle>
And lastly... in your controller where your save() function is put
this.save = function(status) {this.obj.status = status};

Related

Access fileitem from child controller on parent controller in AngularJS

I am using angular file uploader in child component and need to access the fileitem when onAfterAddingFile is fired. I have implemented binding in component. So far, I have tried this-
Childcontroller:
$onInit() {
this.feedFileInfo = 'abc';//here it is updated
this.uploader.filters.push({
name: 'customFilter',
fn: function(item /*{File|FileLikeObject}*/, options) {
return this.queue.length < 10;
}
});
this.uploader.onAfterAddingFile = function(fileItem) {
console.log('fileItem');
this.feedFileInfo = 'xyz';//this value is not being updated to feedFileInfo variable and hence cannot be obtained in parent controller
console.info('onAfterAddingFile', fileItem);
};
I need the updated value ie. fileitem in this variable.
Any guidance would be appreciated.
You use the this from the declared function, not the outer one.
One classical workaround is to use:
var that = this;
this.uploader.onAfterAddingFile = function (fileItem) {
that.feedFileInfo = 'xyz';
};

AngularJS component bindings not passing object

Receiving error cannot read property 'type' of undefined at PollListCtrl.runQuery.
I'm not sure why this is coming up undefined. I've console logged profile-polls.controller.js where listConfig is created to make sure there is an object here. The response is
{type: "all", filters: {pollsCreated: Array(3)}}
But it is coming up undefined when I try to pass it to poll-list component in the profile-polls.html. Below is the gist for the relevant files. Can anyone tell me why this is not passing correctly?
https://gist.github.com/RawleJuglal/fa668a60e88b6f7a95b456858cf20597
I think you need to define watcher for your component. On start listConfig is undefined and only after some delay (next digest cycle) it gets value. So we create watcher and cancel it after if statement.
app.component('pollList', {
bindings: {
listConfig: '='
},
templateUrl: 'poll-list.html',
controllerAs: 'vm',
controller: PollListCtrl
});
function PollListCtrl($scope) {
var vm = this;
function run(){
console.log(vm.listConfig);
}
var cancelWatch = $scope.$watch(function () {
return vm.listConfig;
},
function (newVal, oldVal) {
if (newVal !== undefined){
run();
cancelWatch();
}
});
}
Demo plunkr
You should never use $scope in your angularjs application.
You can use ngOnInit() life cycle hook to access "bindings" value instead constructor.
ngOnInit(){
$ctrl.listConfig = { type: 'all' };
$ctrl.limit = 5;
}

Angular Component Parent Function undefined arguments

I got a component which binds a parent function. I know I have to use non-primitive values as arguments but I still get undefined. What's going on ? Here's a sample code that demonstrates my problem.
Component:
app.component('testComponent', {
template:'<button ng-click="$ctrl.hasStatus({val:700})">Test</button>',
bindings:{
hasStatus:'&'
},
controller:function() {
var ctrl = this;
}
})
Parent:
<test-component has-status='hasStatus(statusObj)'></test-component>
and in the controller:
$scope.hasStatus = function(obj) {
console.log(obj) // undefined
}
And the plunker
As your has-status attribute function has hasStatus(statusObj), where statusObj is parameter of object. That's why you should pass status statusObj property mentioned in JSON, while passing parameter to hasStatus method.
ng-click="$ctrl.hasStatus({statusObj: { val: 700}})"
Demo Plunker

Angular JS - Update Scope value on click

Right now I am passing my parameter through the state like:
.state('app.listing', {
url: '/ad/listing/:adId/{type}',
params: {
adId: {
value: "adId",
squash: false
}, type: {
value: null,
squash: true
}
},
This works as I can get "type" from $stateParams and update my get request.
Is there not a way to do this from a click event and not use $stateParams for passing the "type" param?
I basically have a button that filters results and passes the type param from the button. It would be a lot easier if I can just attach a click event to it which then updates my get request.
Just messing around I tried doing something like
$scope.filter = function(type) {
if(type) {
return type;
}
return '' ;
}
$scope.type = $scope.filter();
Service is like
$http.get(API_ENDPOINT.url + '/listing/' + adId, {
params: {
page: page,
type: type // essentially $scope.type
},
}).
and then on my button I have
<button ng-click="filter('2')"></button>
^ This will pass 2 for type, but won't reinit the http get call on click. Do I need to broadcast the change is there a simple way to do this?
Does this even make sense? The code above is just mock to give an idea, but open to suggestions if any.
Angular never requires you to make broadcasts to reflect changes made to scopevariables via the controller
var typeWatcher = '1';
$scope.filter = function(type){
if (type !== typeWatch)
{
$http.get(API_ENDPOINT.url + '/listing/' + adId, {
params: {
page: page,
type: type // essentially $scope.type
},
});
typeWatcher = type;
}
};
You can wrap your get call in a function & call it after the filter function in ng-click
$scope.functionName = function () {
return $http.get(API_ENDPOINT.url + '/listing/' + adId, {
params: {
page: page,
type: type // essentially $scope.type
}
})
}
then in HTML
<button ng-click="filter('2'); functionName()"></button>
Well, To call $http.get method on click,
$scope.filter = function(type) {
if(type) {
//call the method using service.methodName
return type;
}
return '' ;
}
and wrap that $http.get method to one function.
Hope it helps you.
Cheers

How can I send an object with $broadcast?

I have the following:
$scope.$watch('tableForm.$pristine', function (newValue) {
$rootScope.$broadcast("tableDataUpdated",
{ state: $scope.tableForm.$pristine });
});
I also tried:
$scope.$watch('tableForm.$pristine', function (newValue) {
var tableForm = { pristine: $scope.tableForm.$pristine };
$rootScope.$broadcast("tableDataUpdated", tableForm);
});
When the tableForm $pristine state changes then the value of $scope.tableForm.$pristine is set to False and this message is broadcast.
However when I try to receive the message the value of "state" is not defined:
$rootScope.$on("tableDataUpdated", function (args) {
alert(args.state);
});
I also tried:
$rootScope.$on("tableDataUpdated", function (args) {
alert(args.tableForm);
});
Still I seem not to be able to send the object and have it received
That's because listener function has two arguments being passed into it, event, and args. See the angular docs.
Try:
$rootScope.$on("tableDataUpdated", function (event, args) {
alert(args.state);
});

Resources