I am making a project on my own to practice what I've learned about MEAN stack. In the project I want the user to fill in a form and after it is saved in the database the system to take a use to a second form to fill it in etc. I am angularjs for the front end, and within it I am using ui.route. For some reason my program doesn't go to the second program. I already read about other people with the same problem and I can't find what is wrong with my algorithm. Every form works well by itself or when I Make a call from the toolbar.
Frontend.js
angular
.module('authApp',['auth0', 'angular-storage', 'angular-jwt', 'ngMaterial', 'ui.router',
'AdminUser', 'appProfile', 'appToolbar', 'Mod-Company', 'ModShow'])
.config(function($provide, authProvider, $urlRouterProvider, $stateProvider, $httpProvider, jwtInterceptorProvider,$mdThemingProvider){
/* $mdThemingProvider.theme('docs-dark'); */
$mdThemingProvider.theme('default')
.dark();
$mdThemingProvider.alwaysWatchTheme(true);
authProvider.init({
domain: 'workflowjobs.auth0.com',
clientID: 'SjzgRRh3w4ZEFRGLdglpJYvCPCkM189w'
});
jwtInterceptorProvider.tokenGetter = function(store) {
return store.get('id_token');
}
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'components/home/home.html'
})
.state('company', {
url: '/company',
templateUrl: 'components/company/company.html'
})
.state('singlecompany', {
url: '/singlecompany',
templateUrl: 'components/singlecompany/singlecompany.html'
})
.state('show', {
url: '/show',
templateUrl: 'components/show/show-form.html'
})
.state('ticket', {
url: '/ticket',
templateUrl: 'components/ticket/ticket.html'
})
.state('useradmin', {
url: '/useradmin',
templateUrl: 'components/useradmin/useradmin.html'
})
.state('user', {
url: '/user',
templateUrl: 'components/user/user.html'
})
.state('profile', {
url: '/profile',
templateUrl: 'components/profile/profile.html',
controller: 'profileController',
controllerAs: 'user'
});
From the form I use the controller I need, display the form to be filled in by the user and then I call addcompany() after the user click on the button to save the document on the mongodb database.
<section class="table" ng-controller="CompanyCtrl">
<form name="CompanyForm">
...
<input class="form-control" ng-model="company.name" size="40">
...
<p><md-button class="md-raised md-primary md-hue-1" ng-click="addcompany()" aria-label="next">
Now in this code is where I have the problem. the $location.path('/adminuser') doesn't work:
var app = angular.module('Mod-Company', []);
app.controller('CompanyCtrl', ['$scope', '$http',
function($scope,$http){
var refresh = function() {
$http.get('http://localhost:3001/api/company').success(function(response){
$scope.companylist = response;
$scope.company = "";
});
};
refresh();
$scope.addcompany = function(){
$http.post('http://localhost:3001/api/company', $scope.company).success(function(response) {
refresh();
$location.path('/useradmin');
});
$location.path('/useradmin');
};
Instead of using $location.path('/useradmin'); try $state.go('useradmin');.
If it is still not working, it will be easier to help you if you could share your code in a https://jsbin.com or https://plnkr.co
Related
I an trying to develop an angular app using ui router, however I am stuck trying to get the controllerAs syntax working correctly.
my stateProvider looks like this
$stateProvider
.state('microsite', {
url: "/",
templateUrl: "microsite.tmpl.html",
abstract: true
})
.state('microsite.home', {
url: "",
templateUrl: "home.tmpl.html",
controller: 'MicrositeController as vm',
data: {
page_name: 'Introduction'
}
})
.state('microsite.features', {
url: "/features",
templateUrl: "features.tmpl.html",
controller: 'MicrositeController as vm',
data: {
page_name: 'Features'
}
})
.state('microsite.about', {
url: "/about",
templateUrl: "about.tmpl.html",
controller: 'MicrositeController as vm',
data: {
page_name: 'About'
}
});
As you can see I setup an abstract default view, and three pages.
I have also assigned a data object with a page_name for each page. This feeds into my controller
myapp.controller('MicrositeController', ['$state', function($state) {
var vm = this;
vm.page_name = $state.current.data.page_name;
vm.sidenav_locked_open = false;
vm.toggleSideNav = function() {
if ($mdMedia('gt-sm')) {
vm.sidenav_locked_open = !vm.sidenav_locked_open;
} else {
$mdSidenav('left').toggle();
}
}
}]);
and then delivers the name to the page via the vm.page_name variable.
However this is not happening. The variable never makes it to the page.
Also I have a vm.toggleSideNav function that is suppose to open and close the sidenav, but that never gets called.
the toolbar with the sidenav button is this
<md-toolbar layout="row" class="md-whiteframe-glow-z1 site-content-toolbar">
<div class="md-toolbar-tools docs-toolbar-tools" tabIndex="-1">
<md-button class="md-icon-button" ng-click="vm.toggleSideNav()" aria-label="Toggle Menu">
XXX
</md-button>
<h1>{{vm.page_name}}</h1>
</div>
</md-toolbar>
here is a plnkr example http://plnkr.co/edit/Na5zkF?p=preview
I am looking for someone to help me figure out the last piece on how to get the toggleSideNav function to get called when I click on the xxx button, and how to get the title to display in the toolbar.
From the Docs:
controller
(optional)
string
function
Controller fn that should be associated with newly related scope or the name of a registered controller if passed as a string. Optionally, the ControllerAs may be declared here.
controller: "MyRegisteredController"
controller:
"MyRegisteredController as fooCtrl"
controller: function($scope, MyService) {
$scope.data = MyService.getData(); }
— UI Router $stateProvider API Reference.
According to the Docs, your controller declaration is correct.
controller: 'MicrositeController as vm'
You need to look for your problem elsewhere.
UPDATE
Put the controller in the root state:
$stateProvider
.state('microsite', {
url: "/",
templateUrl: "microsite.tmpl.html",
//IMPORTANT == Put controller on root state
controller: 'MicrositeController as vm',
abstract: true
})
.state('microsite.home', {
url: "",
templateUrl: "home.tmpl.html",
̶c̶o̶n̶t̶r̶o̶l̶l̶e̶r̶:̶ ̶'̶M̶i̶c̶r̶o̶s̶i̶t̶e̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶ ̶a̶s̶ ̶v̶m̶'̶,̶
data: {
page_name: 'Introduction'
}
})
.state('microsite.features', {
url: "/features",
templateUrl: "features.tmpl.html",
̶c̶o̶n̶t̶r̶o̶l̶l̶e̶r̶:̶ ̶'̶M̶i̶c̶r̶o̶s̶i̶t̶e̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶ ̶a̶s̶ ̶v̶m̶'̶,̶
data: {
page_name: 'Features'
}
})
.state('microsite.about', {
url: "/about",
templateUrl: "about.tmpl.html",
̶c̶o̶n̶t̶r̶o̶l̶l̶e̶r̶:̶ ̶'̶M̶i̶c̶r̶o̶s̶i̶t̶e̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶ ̶a̶s̶ ̶v̶m̶'̶,̶
data: {
page_name: 'About'
}
});
})
The DEMO on PLNKR
Try adding the option controllerAs: 'vm' to the state params instead defining the controller as in the controller option.
Try adding the option controllerAs: 'vm' to the state params instead defining the controller as in the controller option.
or, if I'm not mistaken, you can add
myapp.controller('MicrositeController as vm' ...
I'm brand new to Angularjs and am trying to set up a new site but I'm confused as to the set up. I have a module and am using $route to successfully navigate but I'm lost as to what to do with my nav. When I load the module I want to read my database for a list of links that the user is allowed to access then spit them out in the nav. I don't want to repeat this in every view because I don't need to. So I'm trying to figure out how to run the ajax call once and then keep changing the view (I'd also like to add a class .selected to whatever view they're on). How would I go about doing that, with a directive?
(function () {
var app = angular.module('manage', ['ngRoute', 'manageControllers']);
/*
I've tried this but obviously $http isn't injected. Can I even do that?
var thisApp = this;
$http.get('/test/angular/php/angular.php', {params: {'function': 'nav'}}).then(function successCallback(response) {
});
*/
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'templates/dash.html',
controller: 'DashCtrl'
}).
when('/inventory/', {
templateUrl: 'templates/inventory.html',
controller: 'InventoryCtrl'
}).
when('/inventory/:mvKey', {
templateUrl: 'templates/inventory.html',
controller: 'InventoryCtrl'
}).
when('/inventory/:mvKey/:tab', {
templateUrl: 'templates/inventory.html',
controller: 'InventoryCtrl'
}).
/* etc...*/
}
]);
})();
EDIT:
My attempt at getting the nav to run once
controllers.js
var manageControllers = angular.module('manageControllers', []);
var thisApp = this;
nav = null;
navSelected = '/';
manageControllers.controller('NavCtrl', ['$scope', '$http', function($scope, $http) {
if (thisApp.nav === null) {
$http.get('php/angular.php', {params: {'function': 'nav'}}).then(function successCallback(response) {
console.log(response.data);
thisApp.nav = response.data;
$scope.nav = thisApp.nav;
$scope.select = thisApp.navSelected;
});
} else {
$scope.nav = thisApp.nav;
$scope.select = thisApp.navSelected;
}
}]);
manageControllers.controller('DashCtrl', ['$scope', function($scope) {
thisApp.navSelected = '/';
}]);
I would swith to UI Router (https://github.com/angular-ui/ui-router) instead of $route. It allows you being much more flexible with your routing.
A Small example:
app.config(['$stateProvider',
function($stateProvider) {
$stateProvider.
state('/', {
url: '/',
views: {
'': {
templateUrl: 'templates/dash.html',
controller: 'DashCtrl'
},
'nav#': {
templateUrl: 'path/to/nav.html',
controller: 'NavCtrl'
},
}
}).
state('/inventory/', {
url: '/',
views: {
'': {
templateUrl: 'templates/dash.html',
controller: 'DashCtrl'
},
'nav#': {
templateUrl: 'path/to/nav.html',
controller: 'NavCtrl'
},
}
}).
// ...
and in your index.html
<div ui-view="nav"></div>
<div ui-view ></div>
Take a closer look at UI Router's doc, there's much more you can do with it!
I'm trying to redirect after login to a specific page in Meteor using AngularJS. But somehow it is not working. After login Meteor.user() is returning null. Because of this every time it is routing to messages page only. I have seen this example from one of the forums and developed on top of that.
angular.module("jaarvis").run(["$rootScope", "$state", "$meteor", function($rootScope, $state, $meteor) {
$meteor.autorun($rootScope, function(){
if (! Meteor.user()) {
console.log('user');
if (Meteor.loggingIn()) {
console.log('loggingIn ' + Meteor.user()); -- returning null
if(Meteor.user()) {
$state.go('onlineusers');
} else {
//On login
$state.go("messages");
}
}
else{
console.log('login');
$state.go('login');
}
}
});
}]);
Routes declared as below.
angular.module('jaarvis').config(['$urlRouterProvider', '$stateProvider', '$locationProvider',
function($urlRouterProvider, $stateProvider, $locationProvider){
$locationProvider.html5Mode(true);
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'login.ng.html',
controller: 'LoginCtrl'
})
.state('onlineusers',{
url: '/onlineusers',
templateUrl: 'client/onlineusers/onlineusers.ng.html',
controller: 'OnlineUsersCtrl'
})
.state('messages', {
url: '/messages',
templateUrl: 'client/chats.ng.html',
controller: 'ChatCtrl'
})
});
$urlRouterProvider.otherwise("/messages");
}]);
Logging using below snippet of code.
<meteor-include src="loginButtons"></meteor-include>
Michael is probably right about the root cause of the problem, but I think that a better alternative is provided by the the authentication methods of Angular-Meteor.
What you are going to want to do is to force the resolution of a promise on the route. From the Angular-Meteor docs (i.e. a general example...):
// In route config ('ui-router' in the example, but works with 'ngRoute' the same way)
$stateProvider
.state('home', {
url: '/',
templateUrl: 'client/views/home.ng.html',
controller: 'HomeController'
resolve: {
"currentUser": ["$meteor", function($meteor){
return $meteor.waitForUser();
}]
}
});
Your specific code would look something like:
angular.module('jaarvis').config(['$urlRouterProvider', '$stateProvider', '$locationProvider',
function($urlRouterProvider, $stateProvider, $locationProvider){
$locationProvider.html5Mode(true);
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'login.ng.html',
controller: 'LoginCtrl'
})
.state('onlineusers',{
url: '/onlineusers',
templateUrl: 'client/onlineusers/onlineusers.ng.html',
controller: 'OnlineUsersCtrl',
resolve: {
"currentUser": ["$meteor", function($meteor){
return $meteor.waitForUser();
}]
}
})
.state('messages', {
url: '/messages',
templateUrl: 'client/chats.ng.html',
controller: 'ChatCtrl',
resolve: {
"currentUser": ["$meteor", function($meteor){
return $meteor.waitForUser();
}]
}
})
});
$urlRouterProvider.otherwise("/messages");
}]);
And then on your ChatCtrl and OnlineUsersCtrl controllers, you would add currentUser as one of the variables to inject, like:
angular.module("rootModule").controller("ChatCtrl", ["$scope", "$meteor", ...,
function($scope, $meteor, ..., "currentUser"){
console.log(currentUser) // SHOULD PRINT WHAT YOU WANT
}
]);
You might also want to consider the $meteor.requireUser() promise as well, and then send the user back to the login page if the promise gets rejected. All of this is documented very well on the angular-meteor website.
Good luck!
It could be that the user object hasn't loaded yet. You can try:
if ( Meteor.userId() ) ...
instead
I'm using NodeJS+Express to serve an HTML page with an Angular app. It seems to work fine when it loads. There are no errors.
Problem is that that page is pretty much blank - except for the header. But the part that is supposed to go where <div ui-view></div> is, doesn't display anything.
Worse yet, when I go to an address, like
http://localhost:7070/admin/#/rounds
the browser just changes it to
http://localhost:7070/admin/#/
and goes back to displaying nothing.
My angular app, in index.js looks like this:
Some .run() and .config() settings
app.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
// It's very handy to add references to $state and $stateParams to the $rootScope
// so that you can access them from any scope within your applications.For example,
// <li ng-class="{ active: $state.includes('contacts.list') }"> will set the <li>
// to active whenever 'contacts.list' or one of its decendents is active.
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]);
app.config(["$locationProvider", function($locationProvider) {
//$locationProvider.html5Mode(true);
}]);
States definition:
app.config(
['$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
console.log("Is this running at all?");
$urlRouterProvider.otherwise('/');
$stateProvider
.state("admin", {
abstract: true,
url: '/admin',
template: '<ui-view />'
})
.state("admin.login", {
url: '/login',
templateUrl: 'login.html',
controller: 'userLoginCtrl'
})
/* DASHBOARD */
.state("admin.dashboard", {
url: "",
controller: 'dashboardAppCtrl',
templateUrl: "dashboard.html"
})
.state("admin.subjects", {
url: "/subjects",
controller: 'subjectsCtrl',
templateUrl: "subjects.html"
})
/* ROUNDS */
.state("admin.rounds", {
url: "/rounds",
controller: 'roundsAppCtrl',
templateUrl: "rounds.html",
resolve: {
gameId: ['$stateParams', function($stateParams){
console.log("gameId ");
return $stateParams.gameId;
}]
}
})
.state("admin.round", {
url: "/round/:roundId",
controller: 'adminRoundCtrl',
templateUrl: "adminround.html",
resolve:{
gameId: ['$stateParams', function($stateParams){
return $stateParams.gameId;
}],
roundId: ['$stateParams', function($stateParams){
return $stateParams.roundId;
}]
},
});
}
]);
There is a working plunker
The answer is relatively simple
$urlRouterProvider.otherwise('/admin');
And instead of this
http://localhost:7070/admin/#/rounds
we have to try this
http://localhost:7070/admin/#/admin/rounds
The point is, every sub-state 'admin.xxx' is child state of the the 'admin' state. And that means, it inherits its url: '/admin'
Also, we used
//$locationProvider.html5Mode(true);
So, the startingurl would most likely be ...
EXTEND: as discussed in comments, IIS Express is used with virtual applicaton /admin, so this part will be in url twice /admin/#/admin...
http://localhost:7070/admin/index.html
// i.e.
http://localhost:7070/admin/
As a starting url of our app. Any routing is later managed after the # sign
http://localhost:7070/admin/#/admin/round/22
Check it here
I want to be able to use one single route for two different views.
For example right now, I have two routes.
One is /home which is the main page when someone can register/login
And the other one /feed, this is when the user is logged in.
What I want to do is having a single route like twitter for example :
twitter.com/
first they ask you to login
twitter.com/
Than we can see our feed wall. And it's still the same "/". Hope I'm clear :)
This is my code so far:
$stateProvider
.state('index', {
url: '/',
controller: function($state, $auth) {
$auth.validateUser()
.then(function(resp) {
$state.go('feed');
})
.catch(function(resp) {
$state.go('home');
});
}
})
.state('home', {
url: '/home',
templateUrl: 'home.html'
})
.state('feed', {
url: '/feed',
templateUrl: 'feed.html'
})
As far as I remember ui-router doesn't support such feature so you have to do it yourself.
What you can do is to define only a single state as you did in 'index' and instead of performing the $auth logic in the controller do it in a the "resolve" section.
then you can use "ng-if" and "ng-include" to define which .html file and controller you'd like to load, something like this:
app.js
$stateProvider
.state('index', {
url: '/',
resolve: {
isAuthenticated: function() {
return $auth.validateUser().then(function(res) {
return true;
}, function(error) {
return false;
});
}
},
controller: function($scope, isAuthenticated) {
$scope.isAuthenticated = isAuthenticated;
},
templateUrl: 'index.html'
})
index.html
<div ng-if="isAuthenticated">
<div ng-include="'feed.html'"></div>
</div>
<div ng-if="!isAuthenticated">
<div ng-include="'login.html'"></div>
</div>