I dont understand what I am missing
I dont get result on html i think this problem managing with controllerAs syntax
note: I can see the result in console console.log(this.movie); - its from controller
app.js
var app = angular.module('mfApp',['ngRoute', 'appControllers']);
app.config(function($routeProvider){
$routeProvider.
when('/:detail',{
templateUrl: 'template/detail.html',
controller : 'detailCtrl' ,
controllerAs: 'movieAs'
}).otherwise({
redirectTo: '/'
});
});
controller.js
var mfControllers = angular.module('appControllers', []);
mfControllers.controller('detailCtrl', ['$scope', '$routeParams', 'appServices', function($scope, $routeParams, appServices){
this.movie = [];
this.id = $routeParams.detail;
appServices.homeSearch(this.id).success(function(response){
this.movie = response;
console.log(this.movie);
// Yes, I do get array result in console
});
}]);
html - template/detail.html
My try
{{movieAs.Title}}
{{movieAs.movie.Title}}
{{movie.movieAs.Title}}
{{movie.Title}} {{title}}
mfControllers.controller('detailCtrl', ['$scope', '$routeParams', 'appServices', function($scope, $routeParams, appServices){
var me = this;
me.movie = [];
me.id = $routeParams.detail;
appServices.homeSearch(me.id).success(function(response){
me.movie = response;
console.log(me.movie);
// Yes, I do get array result in console
});
}]);
EDIT
In Javascript functions are stored as objects, so from your callbeck method inside succeess, you call this which refers to the method that you are running and not to the controller scope.
It is best practice to store the reference to the controller in a variable which can be accessed by the callback methods. me is quite an arbitrary name but widely used to refer as the parent caller. https://github.com/johnpapa/angular-styleguide
The problem is due to wrong this reference.
var mfControllers = angular.module('appControllers', []);
mfControllers
.controller('detailCtrl', ['$scope', '$routeParams', 'appServices', function($scope, $routeParams, appServices) {
var vm = this;
vm.movie = [];
vm.id = $routeParams.detail;
appServices
.homeSearch(vm.id)
.success(function(response) {
// vm !== this; here
vm.movie = response;
console.log(vm.movie);
});
}]);
A good practice when using controllerAs syntax is to assign this to vm at the very beginning of a controller. It holds the reference of the controller correctly.
That is necessary because of javascript function scoping. It will be long to explain it here, but the gist of it is that function creates a new scope, this inside a function will be different. Todd Mott has a very great write up on this.
Related
I'm trying to write a simple angular service and a factory like below:
html:
<div ng-controller="mycontroller">
{{saycheese}}
</div>
Javascript
var myApp = angular.module('myApp', []);
myApp.service('myservice', function() {
this.sayHello = function() {
return "from service";
};
});
myApp.factory('myfactory', function() {
return {
sayHello: function() {
return "from factory!"
}
};
});
//defining a controller over here
myapp.controller("mycontroller", ["myfactory", "myservice", function(myfactory, myservice) {
$scope.saycheese = [
myfactory.sayHello(),
myservice.sayHello()
];
}]);
But the JSFiddle still just displays {{saycheese}} instead of angular mapping the function.
Link to my fiddle:
http://jsfiddle.net/PxdSP/3047/
Can you point me where am I going wrong in this case ? Thanks.
You have several syntax errors in your code, and checking the console would have helped without questioning the SO. Here's one possible way to write the controller (demo):
myApp.controller("mycontroller", ["$scope", "myfactory", "myservice",
function($scope, myfactory, myservice) {
$scope.saycheese = [
myfactory.sayHello(),
myservice.sayHello()
];
}]);
Apart from obvious fix myapp => myApp (variable names are case-sensitive in JavaScript), $scope should be passed into controller as an argument (and mentioned as its dependency if using arrayed - proper - form of controller definition, as you did) before you can access it. Otherwise you just get ReferenceError: $scope is not defined exception when controller code is invoked.
Couple things:
myapp.controller(...) should be myApp.controller(...)
You need to inject $scope in your controller.
Fixed controller:
myApp.controller("mycontroller", ["myfactory", "myservice", "$scope", function(myfactory, myservice, $scope) {
$scope.saycheese = [
myfactory.sayHello(),
myservice.sayHello()
];
}]);
I get data from remote request by companiesData.getCompanies() and put it into controller variable.
The controller does not wait for promise resolution, figuring the response array empty.
JS controller :
angular.module('X.Exh', [])
.controller('ExhibitorsController', function($scope, $state, $stateParams, companiesData) {
this.companies = [];
companiesData.getCompanies().then(function(response) {
this.companies = response.data;
console.log(this.companies); // working very well
});
});
HTML:
<ion-alpha-scroll ng-model="Exh.companies" key="name" display-key="name" subheader="true" use-complete-alphabet="true">
<!-- Basically the ion alpha scroll is just doing a ng-repeat for every item, it is not the problem here -->
Not waiting for the HTTP request, Exh.companies figures empty. (of course if I don't do this.companies = []; at the beginning of my controller, my HTML says that Exh.companies is undefined.
How do I get data properly?
this inside the unnamed function does not influence original this.companies:
angular
.module('X.Exh', [])
.controller('ExhibitorsController', function($scope, $state, $stateParams, companiesData) {
var vm = this;
vm.companies = []; // you can omit this but for documentation and code clear you can declare it;
companiesData.getCompanies().then(function(response) {
vm.companies = response.data;
console.log(vm.companies); // does not point to local this.companies but to the caller context.
});
});
Please note that vm. runs when you use controllerAs pattern.
Alternatively you can simply access $scope variable:
angular
.module('X.Exh', [])
.controller('ExhibitorsController', function($scope, $state, $stateParams, companiesData) {
$scope.companies = []; // you can omit this but for documentation and code clear you can declare it;
companiesData.getCompanies().then(function(response) {
$scope.companies = response.data;
console.log($scope.companies); // does not point to local this.companies but to the caller context.
});
});
I am trying to share a variable between a controller and a function. But i get an error from the controller, saying this:
TypeError: Cannot read property 'getSet' of undefined
I have gone through numerous tutorials, but don't know where am I going wrong.
My service code is like this:
app.service('shareData', function() {
var selected = ["plz", "print", "something"];
var putSet = function(set) {
selected = set;
};
var getSet = function() {
return selected;
};
return {
putSet: putSet,
getSet: getSet
};
});
I am able to reach selected from my function defined like this:
setDisplay = function($scope, $mdDialog, shareData) {
console.log(shareData.getSet()); // this is working
$scope.selected = shareData.getSet();
$scope.hide = function() {
$mdDialog.hide();
};
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.answer = function(answer) {
$mdDialog.hide(answer);
};
};
My controller is like this:
app.controller('topicController', ['$scope', '$http', '$mdDialog', 'shareData',
function ($scope, $http, $mdDialog, $mdToast, shareData) {
console.log(shareData.getSet()); // NOT WORKING
}]);
You had extra $mdToast in your topicController controller's factory function, you need to remove it.
The reason behind it was not working is, currently you had 4 dependency mentioned in array like ['$scope', '$http', '$mdDialog', 'shareData', function & then you are using its instance inside the function next to DI array. Inside that function you had actually 5 dependencies where $mdToast extra. So behind the scene what happening is $scope of function hold an value of '$scope' DI array likewise you go right to left. But when it comes to $mdToast(in controller function) it was holding a value of 'shareData'(of DI array) & then the next parameter shareData get nothing.
app.controller('topicController', ['$scope', '$http', '$mdDialog', 'shareData',
function ($scope, $http, $mdDialog, shareData) { //<--removed $mdToast
console.log(shareData.getSet());
}
]);
NOTE: You are using DI inline array annotation, so the sequence in which dependency are injected in array, in same sequence you should
inject then in underlying factory function.
I'm using angular js and have got a controller looking like this
myApp = angular.module("myApp.controllers", []);
myApp.controller("ScheduleCtrl", function($scope, $http, ScheduleService){
$scope.hours = 4;
ScheduleService.test();
ScheduleService.initializeSchedule();
});
and a service (in another file) looking like this
myApp = angular.module('myApp.services', []);
myApp.factory('ScheduleService', ['$rootScope', function($rootScope){
return {
test :
function(){
alert("Test");
},
initializeSchedule :
function(){
alert($rootScope.hours);
}
};
});
To assure everyone that things are hooked up properly from service to controller, the first call to "test()" inside my controller produces the desired output in the alert box. However, for the next function, which as of now should be alerting "4", is instead alerting "undefined".
How can I use either $rootScope or something else in order to utilize scope variables to my service.
You need to inject $rootScope into your controller and use $rootScope instead of $scope. DEMO
myApp.controller("ScheduleCtrl", function($scope, $rootScope, $http, ScheduleService){
$rootScope.hours = 4;
ScheduleService.test();
ScheduleService.initializeSchedule();
});
But in this case you don't need to use $rootScope. You can just pass data as parameter into service function.
return {
test :
function(){
alert("Test");
},
initializeSchedule :
function(hours){
alert(hours);
}
};
How to use Angular $rootScope in your controller and view
To share global properties across app Controllers you can use Angular $rootScope. This is another option to share data.
The preferred way to share common functionality across Controllers is Services, to read or change a global property you can use $rootscope.
All other scopes are descendant scopes of the root scope, so use $rootScope wisely.
var app = angular.module('mymodule',[]);
app.controller('Ctrl1', ['$scope','$rootScope',
function($scope, $rootScope) {
$rootScope.showBanner = true;
}]);
app.controller('Ctrl2', ['$scope','$rootScope',
function($scope, $rootScope) {
$rootScope.showBanner = false;
}]);
Using $rootScope in a template (Access properties with $root):
<div ng-controller="Ctrl1">
<div class="banner" ng-show="$root.showBanner"> </div>
</div>
The problem is that $scope is an isolated scope created for your controller. You need to inject the $rootScope into your controller and modify hours on that if you want it to show up in your service.
See more about scope hierarchies here.
controller:
angular.module('myApp', []).controller('ExampleController', ['$scope', '$rootScope', 'ScheduleService', function($scope, $rootScope, ScheduleService) {
$scope.hours = 4;
$rootScope.hours = 42;
ScheduleService.test();
ScheduleService.initializeSchedule();
}]);
service:
angular.module('myApp')
.factory('ScheduleService', function($rootScope) {
return {
test :
function(){
alert("Test");
},
initializeSchedule :
function(childScopeHours){
alert($rootScope.hours);
}
};
});
Working plnkr.
I set a $rootScope variable in one of my modules and now want to access that same $rootScope variable in another module. Thus far I can see that in both modules the variable has been set properly, but when I try accessing the variable in $rootScope, I only get undefined.
How can I access this variable without doing a factory/service workaround? The variable is really simple and $rootScope should suffice for what I need. I've put some generic sample code below to illustrate the issue:
file1.js
var app = angular.module('MyApp1', []);
app.controller('Ctrl1', ['$scope', '$rootScope', function($scope, $rootScope) {
$scope.myFunc = function() {
$rootScope.test = 1;
}
}
file2.js
var app = angular.module('MyApp2', []);
app.controller('Ctrl2', ['$scope', '$rootScope', function($scope, $rootScope) {
$scope.need_to_access_this = $rootScope.test; // undefined
console.log($rootScope); // returns JS object w/ test property set to 1
}
I was just stuck in the same problem when I figured out that you have define those properties for $rootScope before the controllers or services load. So what I did was set inital values when the application runs. In your case it will be like:
app.run(function($rootScope){
$rootScope.test="variable";
})
`
In Ctrl1 the $rootScope.test value is set inside the $scope.myFunc.
The problem is that you aren't calling that function, so the test property in $rootScope is never set.
You need to call $scope.myFunc(); in Ctrl1 or set $rootScope.test = 1; dirrectly in the Controller:
app.controller('Ctrl1', ['$scope', '$rootScope', function($scope, $rootScope) {
$scope.myFunc = function() {
$rootScope.test = 1;
};
$scope.myFunc();
}
or
app.controller('Ctrl1', ['$scope', '$rootScope', function($scope, $rootScope) {
$rootScope.test = 1;
}
EDIT:
The above suggestions still remain valid, thus you need to call myFunc().
But the problem with your code is that Ctrl1 belongs to MyApp1 and Ctrl2 belongs to MyApp2.
Every application has a single root scope (docs here)
You will need to create Ctrl2 as a controller of MyApp1:
angular.module('MyApp1')
.controller('Ctrl2', ['$scope', '$rootScope', function($scope, $rootScope) {
$scope.need_to_access_this = $rootScope.test; // undefined
console.log($rootScope); // returns JS object w/ test property set to 1
}]);