I've been struggling with getting $interval to work. So I was hoping everyone here could straighten me out. Here's my case..
I have a page, that contains a 'update' button. when that button is clicked it's calling a REST service to update a row in a table. On the backend we have a process that monitors that field and runs when it see's the value submitted. Once this process is done it changes the value to completed.
What I'm trying to do is once that button is clicked, a div will display with the status of 'Submitted'. then I want to use $interval to poll that field(via a REST call) and change my view once it's moved to a value of 'completed'. In short change the view from 'Submitted' to 'Completed'.
My problem is when the button is clicked, and I make my rest call if I set my 'data table' on the scope I get
TypeError: Cannot set property 'clst_rfrstatus_data_table' of
undefined
If I change it up and declare the data table like so
var refreshStatus_data_table = StatusService.getRefreshStatus().get({cluster: $stateParams.cluster});
refreshStatus_data_table.$promise.then(function (data) {
for (var x = 0; x < data.message.length; x++) {
$scope.refresh_status = (data.message[x].status == "null") ? data.message[x].status = "" : data.message[x].status;
$scope.$digest;
}
});
},3000);
..snip..
I get
ConsoleAgent: TypeError: Cannot set property 'refresh_status' of
undefined
I'm not following if I am not in scope or what.. Any help is
appreciated.
Code:
myapp-routes.js
myAppconfig(function ($stateProvider, $urlRouterProvider) {
'use strict';
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('status_page', {
url: '/status_page/:cluster',
templateUrl: 'views/clusters/status_page.html',
controller: 'StatusController'
})
..snip..
Controller
clusterApp.controller('StatusController',['$scope','$interval','$state','$stateParams','StatusService', function ($scope, $interval, $state, $stateParams, StatusService) {
$scope.refresh_status = "";
$scope.ButtonClick = function ($scope) {
$scope.refreshStatus_data_table = StatusService.getRefreshStatus().get({cluster: $stateParams.cluster});
$interval( function(){
$scope.refreshStatus_data_table.$promise.then(function (data) {
for (var x = 0; x < data.message.length; x++) {
$scope.refresh_status = (data.message[x].status == "null") ? data.message[x].status = "" : data.message[x].status;
$scope.$digest;
}
});
},3000);
..snip..
} //end controller
view
<div>
<input type="button" value="Update" ng-click="ButtonClick()" />
Status: {{refresh_status}}
</div>
Your method header for ButtonClick expects you to pass in the $scope, but you are calling it without anything, so the local $scope variable is undefined in your method body. You shouldn't need to pass $scope though:
$scope.ButtonClick = function () {
...
}
Related
I have small problem to solve.
I have modal controller rejectIssueModalCtrl.js
(function () {
'use strict';
function rejectIssueModalCtrl($modalInstance, issue, $rootScope) {
var self = this;
self.cancel = function () {
$modalInstance.dismiss('cancel');
};
self.reject = function ($rootScope) {
$modalInstance.close(self.reason);
console.log(self.reason);
};
$rootScope.reasono = self.reason;
}
rejectIssueModalCtrl.$inject = ['$modalInstance', 'issue', '$rootScope'];
angular
.module('app')
.controller('rejectIssueModalCtrl', rejectIssueModalCtrl);
})();
When I click the button I can open this modal and write a reason. I want to show this reject reason in table in other controller.
Here's my code from other controller issueDetailsCtrl.js
$scope.reasonoo = $rootScope.reasono;
function rejectIssue() {
var rejectModal = $modal.open({
templateUrl: '/App/Issue/rejectIssueModal',
controller: 'rejectIssueModalCtrl',
controllerAs: 'rejectModal',
size: 'lg',
resolve: {
issue: self.issueData
}
});
rejectModal.result.then(function (reason) {
issueSvc
.rejectIssue(self.issueData.id, reason)
.then(function (issueStatus) {
changeIssueStatus(issueStatus.code);
getIssue();
}, requestFailed);
});
};
and html code
<div>
<span class="right" ng-bind="$root.reasono"></span>
</div>
As you can see I tried to use $rootScope. I can console.log the reason but I cant make it to show in this html. Any help?
We're missing some context, but I believe this is your problem:
self.reject = function ($rootScope) {
$modalInstance.close(self.reason);
console.log(self.reason);
};
$rootScope.reasono = self.reason;
Assuming self.reason is bound to the input in your modal, it won't be defined outside of the reject callback - that's the nature of async. You're able to log to console because you're doing so within the callback.
Define $rootScope.reasono inside of the callback like so:
self.reject = function () {
$modalInstance.close(self.reason);
console.log(self.reason);
$rootScope.reasono = self.reason;
};
Edited to show that $rootScope should be removed as a named parameter in the reject function definition.
Using root scope is not recommended. For this reason it is recommended to create a service for intercommuncation with variable to store reject reason, then inject this service for each controller - that way you will be able to read/write reason from different controllers.
Hello every body I have a controller:
app.controller('CartController', ['$scope', 'cartDataService', function($scope, cartDataService){
$scope.goodsCount = cartDataService.goodsCount;
$scope.changeQuantity = function (quantity, id) {
if (quantity < 1) {
ngCart.removeItem(id);
} else {
ngCart.getItemById(id).setQuantity(quantity);
}
console.log(ngCart.getTotalItems());
$scope.goodsCount = cartDataService.goodsCount;
}
}]);
And service:
app.service( 'cartDataService', [ '$rootScope', 'ngCart', function( $rootScope, ngCart ) {
return {
goodsCount: ngCart.getTotalItems()
};
}]);
(ngCart is a module, it stores goods in web storage)
And my view on the top of the page:
<div ng-controller="CartController" class="numerik"><% goodsCount %></div>
And view in body of the page:
<div ng-controller="CartController"><% goodsCount %></div>
When I'm calling changeQuantity method, data into the both views doesn't changes. What am I doing wrong, or maybe here I should use other logic?
Angular services are singleton. So when you call your cartDataService it is instantiated and set the value goodsCount what ngCart.getTotalItems() returns, initially it maybe undefined or something.
Next time when you want the updated value from cartDataService.goodsCount it returns initial value Not the changed value
To get updated value you have to set the function and call the function later in your controller like
In service
return {
goodsCount: ngCart.getTotalItems; // pass the function Not executed result. ngCart.getTotalItems() it returns executed result
};
And in controller inside $scope.changeQuantity function
$scope.goodsCount = cartDataService.goodsCount(); //call the function here
This question already has answers here:
Pass value in-between angular JS controller and services
(3 answers)
Closed 7 years ago.
I want to get the variable value which has been assigned inside ng-click function
mainApp.controller('setSearchController',function($scope) {
$scope.getQuery = function(userq) //ng-click function
{
$scope.userq=userq;
};
alert($scope.userq); // showing Undefined even after the click is made
// Once clicked I want to use **userq** value to make one $https call
// apart from services,How to use userq here outside getQuery scope
});
before using ng-click , its ok to get undefined value but what I am trying to do is to use the same controller for another view , which will be rendered after the ng-click happens
.when('/search', {
templateUrl: "../static/views/seachResult.html",
controller: "setSearchController"
})
so I want to fetch some searched data in searchResult.html view after $https call
Take a look at my answer here:
Pass value in-between angular JS controller and services
It is the same question, I have solved your problem with event listeners using $on and $emit
HTML:
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="getQuery('myVal')">Test</button>
<button ng-click="consoleIt(myVal)">Console</button>
</div>
Controller:
angular.module('myApp', [])
.controller('myCtrl', ['$scope', function($scope) {
$scope.getQuery = function(a){
$scope[a] = a;
}
$scope.consoleIt = function(a){
console.log(a);
}
}]);
The getQuery function creates a new property on your scope. The property's name is equal to what is passed (string) as agrument to the function. consoleIt simply console logs its agrument. myVal is undefined until you click the test button. You can also pass a variable (instead of string) to getQuery, in this case just remove the quotes from inside of parenthesis.
Move alert inside statement function getQuery.
mainApp.controller('setSearchController', function($scope) {
$scope.userq = null;
$scope.getQuery = function(userq) //ng-click function
{
$scope.userq=userq;
alert($scope.userq);
};
});
or this solution
mainApp.controller('setSearchController', ['$scope', '$window', setSearchController]);
function setSearchController ($scope, $window) {
$scope.userq = null;
$scope.getQuery = function(userq) //ng-click function
{
$scope.userq=userq;
$window.alert($scope.userq);
};
}
I am trying to create a service when I can set my formSubmit.
For example. In controller A I call "service.setFormSubmit(doThis(obj))" and in controller B I call "service.getFormSubmit()". Where it will execute the function doThis(obj) in controller B.
UPDATE - Re-formulated question.
I have 1 view where I want to edit or create a category. This means I need a dynamic ng-submit. I want to to this in the controller. So like this:
$scope.editCategory = function(obj) {
$scope.formSubmit = 'editCategory'
}
And on the create I want to change the formSubmit var to createCategory of course.
So I can make a difference between creating and editing the category.
Is this possible? Would be really nice if someone has a way to do this..!
Thanks in advance!
Instead of passing around strings which need to be eval'ed, use the service to share functionality directly between controllers.
The service can be dirt-simple:
.factory('MyService', function(){
var service = {};
return service;
});
Once injected and assigned to scope variables in both controllers you have an intermediary unit which can act as a modifiable channel for cross-controller collaboration.
.controller('FirstController', function($scope, MyService){
$scope.service = MyService;
})
.controller('SecondController', function($scope, MyService){
$scope.service = MyService;
$scope.service.create = function(obj){
console.log('Creating');
}
$scope.service.edit = function(obj){
console.log('Editing');
}
})
From the scope of FirstController, you can now call the function also available on the scope of SecondController:
<div ng-controller="FirstController">
<input type="checkbox" ng-model="button.type"> Toggle create/edit<br/>
<button ng-if="button.type" ng-click="service.create(obj)">Create</button>
<button ng-if="!button.type" ng-click="service.edit(obj)">Edit</button>
</div>
Demo
If you aren't reloading the page you can create an encapsulated variable in your service. Your set call would assign the value passed to that variable and your get call would return that variable to the caller.
One way I have achieved passing the data is to submit the form using the service and return a Json result to the service. Store the Json object in the encapsulated variable on the return and then pass a success or failure to the controller. When successful, let the controller redirect the view which will redirect using angular routing and ng-view. Once the new view, along with the new controller is loaded into the page, you can call the variable in your service to retrieve the data on the next controller.
Example Code:
app.factory('service', function ($q, $http) {
var savedData;
return {
loadData: function() {
return data;
},
search: function (parameters) {
var searchURL = '/MVCController/Search?parameter1=' + parameters.one +
'¶meter2=' + parameters.two;
var deferred = $q.defer();
$http.get(searchURL).success(function (data) {
savedData = data;
deferred.resolve(true);
}).error(function(data) {
data = 'An error occurred while searching: ' + data;
savedData = data //(if you want to save the error)
deferred.reject(data);
});
return deferred.promise;
}
}
});
I have Two nested controllers:
BuildingsShowCtrl = ($scope, $location, $routeParams, Building) ->
$scope.building = Building.get
id: $routeParams.id
AddressesChildCtrl = ($scope, $routeParams, Address) ->
$scope.addresses = Address.query({building_id: $scope.building.id})
They are used this way in my nested views:
<div ng-controller="BuildingsShowCtrl">
<h1>Building</h1>
<p>
<b>Name</b><br>
{{building.name}}
</p>
<p>
<b>Number</b><br>
{{building.number}}
</p>
<div ng-include="'/assets/addresses/index.html'"></div>
</div>
When I hit refresh on the browser, it works fine but when I click a building from a building lists page, it fails because $scope.building is undefined in AddressesChildCtrl.
Why doesn't the child controller have access to the parent controller's scope in this case?
The app is visible here: http://lgi.herokuapp.com/buildings/
Thx!
If you are using ngResource, Building.get will return an empty object immediately and will asynchronously fill in the object data after the HTTP request is complete (documentation). You can do something like this to load the address data when the object is filled in:
AddressesChildCtrl = function($scope, $routeParams, Address) {
$scope.$watch('building.id', function(newValue, oldValue) {
if (newValue) {
$scope.addresses = Address.query({building_id: $scope.building.id})
} else {
$scope.addresses = []
}
}, true);
}