Trouble connecting controller using routing in AngularJS - angularjs

Ill try and do my best to explain...
It doesn't seem like my controller is connecting/working properly. I'm not sure exactly why, every time I check my syntax seems correct. Here is my route declaration:
angular.module('portfolio', ['ngRoute']).config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/', {
templateUrl: '/public/app/views/main.html',
controller: 'MainCtrl',
controllerAs: 'main'
}).when('/about', {
templateUrl: '/public/app/views/about.html',
controller: 'AboutCtrl',
controllerAs: 'about'
}).when('/Resume', {
templateUrl: '/public/app/views/resume.html',
controller: 'ResumeCtrl',
controllerAs: 'Resume'
}).when('/Samples', {
templateUrl: '/public/app/views/samples.html',
controller: 'SamplesCtrl',
controllerAs: 'Samples'
}).otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(false).hashPrefix('');
});
Just as an example here is my resume view:
<paper-button ng-click="changeEx()" raised>Experience</paper-button>
<paper-button ng-click="changeSkills()" raised>Skills</paper-button>
<paper-button ng-click="changeEdu()" raised>Education</paper-button>
<paper-button ng-click="changeMisc()" raised>Misc.</paper-button>
<div ng-hide="exp">
<p>Experience</p>
</div>
<div ng-show="skills">
<p>Skills</p>
</div>
<div ng-show="education">
<p>Education</p>
</div>
<div ng-show="misc">
<p>Misc.</p>
</div>
Finally, here is the declaration of the controller for the resume view:
angular.module('portfolio', []).controller('ResumeCtrl', function () {
this.exp = true;
});
Obviously, this controller is incomplete but I am simply trying to test it by using this variable.

Do not use square brackets when you are referencing a module that has already been declared. This is interpreted by Angular as declaring a new module:
angular.module('portfolio').controller('ResumeCtrl', function () {
this.exp = true;
});
The next thing I would check is your main HTML page. Do you have this directive somewhere on your page:
<div ng-view></div>
Another problem is that you are declaring controllerAs in your route as Resume, but you are using this.exp to assign your variable and also trying to reference exp in your view. You need to follow this pattern instead, or use $scope:
angular.module('portfolio').controller('ResumeCtrl', function () {
var Resume = this;
Resume.exp = true;
});
And in your view you should reference the variable using the same name you defined in controllerAs:
<div ng-hide="Resume.exp">
<p>Experience</p>
</div>
Or, alternatively, you can keep your view the same, but assign your variable using $scope:
angular.module('portfolio').controller('ResumeCtrl', function ($scope) {
$scope.exp = true;
});

Related

ui-router, factory share data

Hy,
I want to share data between 1 component (NavBar) and other 1 ctrl (Ctrl1) in ui-view with factory, but it's not work.
When i modify factory in component or ctrl, it modify only his own scope. I want to share factory between ctrl and component.
HTML :
<div ng-app="myApp">
<global-component></global-component>
</div>
Javascript :
var myApp = angular.module('myApp', [ 'ui.router']);
myApp.config(function ($stateProvider, $urlRouterProvider){
$stateProvider.state("state1", {
url: "#",
template: "<p>State 1 </p> <input type=\"text\" ng-model=\"vm.b\"/> {{vm.b}}",
controller: "Ctrl1",
controllerAs: 'vm'
});
$urlRouterProvider.otherwise(function($injector, $location) {
$injector.get('$state').go("state1");
});
});
//Global Component
myApp.component('globalComponent', {
template: 'Global controler </br> <nav-bar></nav-bar> <div ui-view></div>',
controller: "GlobalCtrl",
controllerAs: 'vm'
});
myApp.controller('GlobalCtrl',function(Data){
Data.test="test1";
});
//NavBar
myApp.component('navBar', {
template: 'NavBar <input type=\"text\" ng-model=\"vm.a\"/> {{vm.a}}',
controller: "NavBarCtrl",
controllerAs: 'vm'
});
myApp.controller('NavBarCtrl',function(Data){
var vm=this;
vm.a=Data.test;
});
myApp.controller('Ctrl1',function(Data){
var vm=this;
Data.test="titi";
vm.b=Data.test;
});
myApp.factory('Data', function(){
var data={};
data.test="";
return data;
});
The code :
https://codepen.io/anon/pen/YrdvbV?editors=1111
Thanks
Check out working solution here.
The reason why it's wasn't working in the first palce is that you have changed the reference to data in your setData method. When the reference is changed, your are not working with the same object as before so this vm.a=Data.getData(); is not bound to the same object as on initialization.
In your case, one way to resolve this is to wrap an object around your data (in the example provided, I used data.item instead of just data). Other options are to use $watch or something similar so values could be rebound to ng-model.

angularjs - ng-show does not woking

I use ng-show to show or hide navigator.
In index.html :
<div class="container" ng-show="vm.error" nav></div>
In app.js
var siteApp = angular.module('siteApp', ['ngRoute']);
siteApp.config(function($routeProvider) {
$routeProvider
.when('/', {
controller: 'HomeController',
controllerAs: 'vm',
templateUrl: '/home.html'
})
.when('/404', {
controller: 'ErrorController',
controllerAs: 'vm',
templateUrl: '/404.html'
});
});
In HomeController.js
siteApp.controller('HomeController', function(){
var vm = this;
vm.error = false;
vm.message = "Halu home page";
});
In ErrorController.js
siteApp.controller('ErrorController', function(){
var vm = this;
vm.error = true;
vm.message = "Error 404";
});
My navigator hides in both of pages although vm.message show true. Why ?
You can help me at : https://github.com/ryantranvn/mean
As this SO answer discusses regarding using this in place of $scope:
When using this style, directives should use the controllerAs property in their return object per the Directive documentation.
A quick workaround for you would be to preface variable names with $scope if you want them to be available in the view:
siteApp.controller('HomeController', function(){
$scope.error = false;
$scope.message = "Halu home page";
});
<div class="container" ng-show="error" nav>{{message}}</div>
As to why the text was being hidden in both your test cases, the variable being used in ng-show was not defined.
Since you are using "this" in the controller function, you will have to declare your Controller with "as" syntax.
If you are using routes to bind the controller, add below code in routes
controller: "HomeController",
controllerAs: "HomeCtrl"
Or if you are directly writing ng-controller in html, use below code
<div ng-controller="HomeCtrl as HomeController">
<div class="container" ng-show="HomeCtrl.error" nav></div>
</div>

using $rootScope in templateUrl function

I just started with angularJS and I have a question:
How can I access a variable defined with $rootScope in a templateUrl function?
Here is my code:
myApp.config(['$routeProvider',
function($routeProvider, $rootScope) {
$routeProvider.
when( '/', {
templateUrl: 'partials/login.html',
controller: 'loginCtrl'
}).
when( '/home', {
templateUrl: function($rootScope){
console.log($rootScope.utilisateur.user.role_id);
if ($rootScope.utilisateur.user.role_id==2){
return 'partials/home.html';
}
else return 'partials/login.html';
},
controller: 'homeCtrl'
}).
otherwise({redirectTo:'/'});
}]);
It tells me that utilisateur is undefined.
I defined it in the index controller:
$rootScope.utilisateur = null;
$rootScope.rapports = null;
And then in the LoginCtrl:
var user = Authentification.login(email,password);
user.success(function(response){
$rootScope.utilisateur = response;
console.log($rootScope.utilisateur);
$location.path('/home');
});
You cannot use the $rootScope inside of the config block, as the config block runs before the $rootScope is created. Constants and providers may be used inside of the config block instead. If constants are not an option for you, you may want to redirect to the correct url inside of your homeCtrl.
[EDIT] Added possible solution from comment below:
Option 1: Have 2 different routes
/admin/home
/home
Option 2: Switch templates according to permission inside of controller/view
home.html
<div ng-switch="utilisateur.user.role_id">
<div ng-switch-when="2">
<!-- is admin -->
</div>
<div ng-switch-default>
<!-- not admin -->
</div>
</div>
Not the ideal solution, but it'd work for what you are trying to do, based on your comments below
Your problem seems like you have two different views, and on condition base you have to redirect views.
Pass the parameters in url like from your views (Create/Edit link etc.) As i have set the cookie on login and accessed here as a parameters or you can use different way to access the parameters.
''
And your config in $routeProvider use like this:
$routeProvider.when("/editTest/:ID/:flagTab",
{
templateUrl: function (params) {
var flag = params.flagTab;
if (flag == 'tabPanelView') {
return '/apps/templates/editTest.html';
}
else {
return '/apps/templates/editTestPageView.html';
}
},
controller: 'EditTestController'
});.
Refere a link swtiching views in routeProvider based on condition
Instead of describing different ways to achieve what you would like to, the code snippet below answers the actual question that was asked:
How can I access a variable defined with $rootScope in a templateUrl function?
The answers above and here imply there is no way to reference $rootScope within the config/$routeProvider. While that may strictly be true, there is a simple way to access the $rootScope through $routeProvider. Below is how to do this:
Sample HTML:
<div ng-app="myApp">
<div ng-controller="masterController">
<script type="text/ng-template" id="home.html">{{something}}</script>
Page
<div ng-view></div>
</div>
</div>
Sample javascript:
var myApp = angular.module('myApp',[],function($routeProvider) {
$routeProvider
.when('/home',{templateUrl:'home.html'})
.when('/page',
{
template:'<p>{{something}}</p>',
controller:'masterCtrlWrapper'
})
.otherwise({redirectTo:'/home'});
});
myApp.controller('masterCtrlWrapper', function($rootScope)
{ $rootScope.changeVariable(); });
myApp.controller('masterController', function($rootScope)
{
$rootScope.something = 'This is the $rootScope talking.'
$rootScope.pressCount = 0;
$rootScope.changeVariable = function()
{ $rootScope.something = "This function was run " + $rootScope.pressCount++ + " times."; };
});
Like others have said, $rootScope doesn't exist yet, but unlike their answers, it doesn't at all mean you can't use it at all, you just have to code-in the wait.
Here is your example working but just printing since we dont have the templates.
myApp
.provide('home', function() {
var $rootScope = null;
this.templateUrl = function() {
var check =
$rootScope.utilisateur &&
$rootScope.utilisateur.user.role_id
;
console.log(check);
return (check) ? 'partials/home.html' : 'partials/login.html';
};
this.controller = 'homeCtrl';
this.resolve = {load:['$rootScope', function(fetched) { $rootScope = fetched; }]};
this.$get = function() { };
})
.config(['$routeProvider', 'homeProvider', function($routeProvider, homeProvider) {
$routeProvider
.when('/', {
templateUrl : 'partials/login.html',
controller : 'loginCtrl'
})
.when('/home', homeProvider)
.otherwise({redirectTo:'/'})
;
}])
;

Pass variable from $routeProvider to View

How can I pass a variable from $routeProvider to a view file:
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/send-money', {
templateUrl: 'partials/send-money.html',
controller: 'PageCtrl'
})
.when('/receive-money', {
someURL: 'goToSomePage',
templateUrl: 'partials/receive-money.html',
controller: 'PageCtrl'
})
}]);
As you can notice on top:
.when('/receive-money') i have declared (someURL: 'goToSomePage')
but .when('/send-money') i have not declared (someURL)
Below is the code that I would like to make it work, without taking help of controller. Is that possible ? even I am not sure something like ng-if="someURL" will work.
<div ng-if="someURL">
<a ng-href="someURL" class="nav-back"> <i class="ico-back"></i> </a>
<div>
If you don't want to use controller you can use run block to pass a reference to route service into $rootScope, from where you could check if current route has property someURL:
app.run(function($route, $rootScope) {
$rootScope.$route = $route;
});
Now in template you could use $route.current in ngIf:
<div ng-if="$route.current.someURL">
<a ng-href="someURL" class="nav-back"><i class="ico-back"></i></a>
</div>
Demo: http://plnkr.co/edit/3XUl0QprIAj1PcnnHx9Q?p=preview

When using angular-ui-router, what is the suitable structure for controller?

Before use angular-ui-router, one controller always support several router&views, such as:
$routeProvider.
when('/posts', {
templateUrl: 'views/posts/list.html'
}).
when('/posts/create', {
templateUrl: 'views/posts/create.html'
}).
all views for one object share one controller:
app.controller('PostsCtrl', function($scope) {
$scope.create = function() {
// ...
}
$scope.list = function() {
// ...
}
});
and init data in view:
<div data-ng-controller="PostsController" data-ng-init="list()">
...
</div>
But in angular-ui-router, we use state, so we need create several controller for each state, such as:
$stateProvider
.state('posts', {
abstract: true,
url: '/posts',
templateUrl: 'views/posts/list.html',
controller: 'PostsCtrl'
})
.state('posts.detail', {
url: '/:postId',
templateUrl: 'views/posts/detail.html',
controller: 'PostsDetailCtrl'
})
Separating controller seems not a good design pattern.
So, is there any better suggestion to structure controllers?
It is a little late for an answer, but as I was struggling with it and found an answer, I might as well post it.
I agree with Nate's comment that in most circumstances you should keep the controllers as small as possible, i.e. you should write a separate controller for every state. However, if you find yourselves in a situation that really think that using the same controller for both the parent and child views is preferable you can simply omit the controller option in the child view. This view will then use the state of the parent. This can be read in the documentation. A little example:
app.js
app.controller('testController', ['$scope', function($scope){
$scope.message= 'This comes from testController';
}]);
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider ,$urlRouterProvider) {
$stateProvider
.state('test', {
url: '/test',
templateUrl: 'partials/test.html',
controller: 'testController'
})
.state('test.child', {
url: '/child',
templateUrl: 'partials/test2.html'
});
}]);
partials/test.html
<div>
Test.html: {{message}}
<div data-ui-view></div>
</div>
partials/test2.html
<div>
Test2.html: {{message}} as well.
</div>
This will produce the following (with url #/test/child)
Test.html: This comes from testController
Test2.html: This comes from testController as well.
I hope this helps anyone

Resources