Related
I got the next controller:
.controller('LogInController', function(logInFactory, $scope, $location, $state){
$scope.logIn = function() {
$scope.dataLoading = true;
logInFactory.logIn($scope.email, $scope.password, function (response) {
if (response.success) {
$scope.userName = response.userName;
console.log('userName', $scope.userName);
logInFactory.setCredentials($scope.email, $scope.password);
$location.path('/users');
} else {
$scope.dataLoading = false;
}
});
};
$scope.clearCredentials = function(){
$state.go('login');
logInFactory.clearCredentials();
};
});//End controller
I want to use it in this view:
<div class="header" ng-controller = 'LogInController'>
<img src= "logo.jpg">
{{userName}}
<button ng-click = 'clearCredentials()'> Cerrar sesión</button>
</div>
But userName is not showing in the view but when I print it on the controller it is displayed correctly. That view is displayed after call the logIn() function.
This is the logIn function in my factory:
var logIn = function(email, password, callback){
var URL;
if(ENV.mocksEnable){
URL = ENV.apiMock + ENV.logInMock;
return (
$timeout(function () {
var response;
getUser()
.then(function (user) {
console.log('USER', user);
if (user !== null) {
response = { success: true, userName: user.userName};
} else {
response = { success: false, message: 'Username or password is incorrect' };
}
callback(response);
});
}, 1000)
);
}else{
URL = ENV.apiURL + ENV.logIn;
return (
$http.post(URL, {email : email, password : password})
.then(function onFulfilled(response){
var data = response.data;
userName = data.username;
userEmail = data.email;
userId = data.id;
profiles = data.profiles;
callback(response);
return data;
})
.catch(function onRejected(errorResponse){
console.log('Error in logInFactory');
console.log('Status: ', errorResponse.status);
callback(errorResponse);
return errorResponse;
})
);
}
};//End login
I trigger the logIn() function in this view
<form ng-submit = 'logIn()'>
<h1>Log In</h1>
Correo electrónico:
<input type="email" ng-model='email' required><br>
Contraseña
<input type="password" ng-model='password' required><br>
<input type="submit" value="Log in">
</form>
When I tigger logIn() I should go to that header and show the userName.
why are you triggering clearCredentials() ? whereas according to this code you should triggering login() instead.
The result of your logIn() function may be out of Angular scope.
Try wrapping the result of the logIn function into a $timeout (which calls $apply, a way to force Angular to refresh a controller scope):
$timeout(function() {
if (response.success) {
$scope.userName = response.userName;
console.log('userName', $scope.userName);
logInFactory.setCredentials($scope.email, $scope.password);
$location.path('/users');
} else {
$scope.dataLoading = false;
}
});
Do not forget to inject the dependency $timeout in your controller.
You have $scope.userName inside the success of the logIn method. It won't be available until that has happened.
If you put $scope.userName outside of the method and set it to something, it would appear.
.controller('LogInController', function(logInFactory, $scope, $location, $state) {
$scope.userName = 'test name';
$scope.logIn = function() { ...
Something like that.
we don't have your factory code but this line is very strange to me :
logInFactory.logIn($scope.email, $scope.password, function (response) { ..; } )
so your passing the fonction to the factory and it is not the factory who returning data to the controller.
it should be something like this :
logInFactory.logIn($scope.email, $scope.password).then(function (response) { ..; } );
EDIT :
You have to remove the callback function from your factory and make the factory return data and handle data like this logInFactory.logIn($scope.email, $scope.password).then(function (response) { ..; } );.
You have log in the console but the $scope is not shared between the factory and controller so the callback in your factory edit the $scope.userName but the controller cannot get this change.
My problem was that I was expecting to get data from a controller to two different views. And when I go from LogIn view to my header view, the controller refresh its data. So, I have to create in my factory:
var getUserName = function() {
return userName;
};
And in the controller
$scope.userName = logInFactory.getUserName();
Now my userName persists in the factory.
I'm trying to display the results from a submitted form, AngularJS > PHP > Back but I'm getting nothing. I've tried a lot of different ways and according to all of google I'm doing it right but the console log just says that it's undefined.
Here is the submit function:
$scope.testProcessForm = function() {
$http({
method : 'POST',
url : 'test.php',
data : $scope.formData,
headers : {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
})
.success(function(data) {
if (data.errors) {
// Showing errors.
$scope.errorselectedServices = data.errors.selectedservices;
$scope.errorincEmail = data.errors.incemail;
} else {
$scope.submissionMessage = data.messageSuccess;
$scope.test= data.test;
The PHP:
$data['test'] = $test;
echo json_encode($data);
HTML:
<div ng-show="test">{{test}}</div>
Why am I getting "test is undefined" and no div? If I put an echo into PHP I get the proper reply back. It doesn't appear to hang anywhere in the code after some debugging. What am I doing wrong?
// app.js
// create our angular app and inject ngAnimate and ui-router
// =============================================================================
angular.module('formApp', ['ngAnimate', 'ngMessages', 'ui.router'])
// configuring our routes
// =============================================================================
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
// route to show our basic form (/form)
.state('form', {
url: '/form',
templateUrl: 'form.html',
controller: 'formController'
})
// nested states
// each of these sections will have their own view
// url will be nested (/form/profile)
.state('form.tjanst', {
url: '/tjanst',
templateUrl: 'form-tjanster.html'
})
// url will be /form/interests
.state('form.epost', {
url: '/epost',
templateUrl: 'form-epost.html'
})
// url will be /form/payment
.state('form.fax', {
url: '/fax',
templateUrl: 'form-fax.html'
})
// url will be /form/payment
.state('form.sms', {
url: '/sms',
templateUrl: 'form-sms.html'
})
// url will be /form/payment
.state('form.mcl', {
url: '/mcl',
templateUrl: 'form-mcl.html'
})
// url will be /form/payment
.state('form.review', {
url: '/review',
templateUrl: 'form-review.html'
});
// catch all route
// send users to the form page
$urlRouterProvider.otherwise('/form/tjanst');
})
.value('formSteps', [
{uiSref: 'form.tjanst', valid: false},
{uiSref: 'form.epost', valid: false},
{uiSref: 'form.fax', valid: false},
{uiSref: 'form.sms', valid: false},
{uiSref: 'form.mcl', valid: false},
{uiSref: 'form.review', valid: false}
])
.run([
'$rootScope',
'$state',
'formSteps',
function($rootScope, $state, formSteps) {
// Register listener to watch route changes
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
var canGoToStep = false;
// only go to next if previous is valid
var toStateIndex = _.findIndex(formSteps, function(formStep) {
return formStep.uiSref === toState.name;
});
console.log('toStateIndex',toStateIndex)
if(toStateIndex === 0) {
canGoToStep = true;
} else {
canGoToStep = formSteps[toStateIndex - 1].valid;
}
console.log('canGoToStep', toState.name, canGoToStep);
// Stop state changing if the previous state is invalid
if(!canGoToStep) {
// Abort going to step
event.preventDefault();
}
});
}
])
// our controller for the form
// =============================================================================
.controller('formController', function($scope, $state, $http, formSteps) {
// we will store all of our form data in this object
$scope.formData = {};
$scope.submission = false;
$scope.formStepSubmitted=false;
$scope.formData.selectedServices = {};
$scope.messitServices = [{'name':'Fax', 'id':1}, {'name':'SMS', 'id':2}, {'name':'Minicall', 'id':3}];
$scope.someSelected = function (object) {
return Object.keys(object).some(function (key) {
return object[key];
});
};
var nextState=function(currentState) {
switch (currentState) {
case 'form.tjanst':
return 'form.epost'
break;
case 'form.epost':
return 'form.fax'
break;
case 'form.fax':
return 'form.sms'
break;
case 'form.sms':
return 'form.mcl'
break;
case 'form.mcl':
return 'form.review'
break;
default:
alert('Did not match any switch');
}
};
var updateValidityOfCurrentStep=function(updatedValidity) {
var currentStateIndex = _.findIndex(formSteps, function(formStep) {
return formStep.uiSref === $state.current.name;
});
formSteps[currentStateIndex].valid = updatedValidity;
};
$scope.goToNextSection=function(isFormValid) {
console.log('isFormValid ', isFormValid);
// set to true to show all error messages (if there are any)
$scope.formStepSubmitted = true;
if(isFormValid) {
// reset this for next form
$scope.formStepSubmitted = false;
// mark the step as valid so we can navigate to it via the links
updateValidityOfCurrentStep(true /*valid */);
$state.go(nextState($state.current.name));
} else {
// mark the step as valid so we can navigate to it via the links
updateValidityOfCurrentStep(false /*not valid */);
}
};
$scope.testProcessForm = function() {
$http({
method : 'POST',
url : 'kundreg.php',
data : $scope.formData,
headers : {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
})
.success(function(data) {
if (data.errors) {
// Showing errors.
$scope.errorselectedServices = data.errors.selectedservices;
$scope.errorincEmail = data.errors.incemail;
} else {
$scope.submissionMessage = data.messageSuccess;
$scope.faxSenderPhoneNo = data.faxSenderPhoneNo;
$scope.faxSender = data.messit.faxSender;
console.log(faxSender);
// $scope.formData = {};
}
});
};
});
<!DOCTYPE html>
<h3 class="text-center">Granskning</h3>
<h4 class="text-center">Vänligen kontrollera:</h4><br>
<div class="form-group row"></div>
<!-- <span ng-show="errorselectedServices">{{errorselectedServices}}</span>
<span ng-show="errorincEmail">{{errorincEmail}}</span>></div> -->
<div ng-show="faxSender">{{ faxSender }} ng show faxsenderphoneno</div>
<br>
<div class="form-group row">
<div class="col-xs-6 col-xs-pull">
<a ui-sref="form.fax" class="btn btn-block btn-info">
Föregående <span class="glyphicon glyphicon-circle-arrow-left"></span></a>
</div>
<div class="col-xs-6 col-xs-push">
<a ng-click="testProcessForm()">
Skapa <span class="glyphicon glyphicon-circle-arrow-right"></span>
</a>
</div>
</div>
<?php
$errors = array();
$data = array();
$selectedServices = array();
// Getting posted data and decodeing json
$_POST = json_decode(file_get_contents('php://input'), true);
// checking for blank values.
if (empty($_POST['selectedServices']))
$errors['selectedServices'] = 'Minst en tjänst måste väljas.';
if (empty($_POST['incEmail']))
$errors['incEmail'] = 'Epost som tillåts använda tjänsterna saknas';
$selectedServices = $_POST['selectedServices'];
if (!empty($errors)) {
$data['errors'] = $errors;
} else {
if (!empty($_POST["faxSenderPhoneNo"])) {
// ta bort allt som inte är siffror
$faxSender = preg_replace('/[^0-9\/+]/', '', $_POST["faxSenderPhoneNo"]);
// finns ingen nolla så lägger vi till den så vi kan matcha den i regexen
//regex med internationellt format så databasen blir glad
if (preg_match('/^0/', $faxSender) === 0) {
$faxSender = "0{$faxSender}";
}
$faxSenderPhoneNo = preg_replace("/(^0|^46)/", "+46", $faxSender);
$messit['faxSender'] = $faxSenderPhoneNo;
}
else {
$faxSenderPhoneNo = 'NULL';
}
if (!empty($_POST["deliveryReportFax"])) {
$deliveryReportFax = $_POST["deliveryReportFax"];
}
else {
$deliveryReportFax = '3';
}
}
}
if (!$error) {
// sql
echo json_encode($data);
?>
I found the error. Apparently you have to quote the variable into the array;
$data['faxSender'] = "$faxSenderPhoneNo";
Now works as intended.
EDIT:
Well it worked to a point. My divs still weren't displaying. After logging with console.log(data) I could see that I had a lot of undefined indexes but my data array was there so I didn't understand why I couldn't access it.
I fixed the undefined stuff and then suddenly every div was displayed. Not a clue why PHP decides to dump all that info into my $data array.
2nd edit: Apparently .success is deprecated. Using .then instead with error_reporting(1); seems to always give me an array with data that angular then can use.
Since you are JSON encoding data in php file, file returning a String. so, you will need decode JSON to Java script object first. Also, you $http returns angular promise($q service). I am not sure about using
.success
method. Instead use
.then
.then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
// decode JSON firs since you are sending JSON from PHP
var data = JSON.parse(response);
$scope.test = data.test;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
// Handle error here
});
Currently I am working on my master project. My application is online portfolio management. User can register on app and create profiles. Now i want to give Edit and Delete buttons on the profile view. But just the users who have created the profile are able to see this buttons. For example, if i am a user of app then only i can see the edit and delete buttons on my profile and i can only see the other user's profile.
I am new in AngularJS. It looks easy but still did not work for me. I have a different views of view profile and edit profile. But i have just one controller for both of it.
This is how my view profile code looks like,
HTML
<section data-ng-controller="ProfilesController as profilesCtrl">
<div class="modal-header">
<div>
<h1>{{profile.firstname}} {{profile.lastname}}</h1>
</div>
<div class="pull-right">
<button class="btn-success btn-lg" type="button" data-ng-click="profilesCtrl.modalUpdate('lg', profile)">Edit</button>
<button class="btn-danger btn-lg" type="button" data-ng-click="profilesCtrl.remove(profile)">
<i class="glyphicon glyphicon-trash">
</i>
</button>
</div>
</div>
</section>
Controller
profilesApp.controller('ProfilesController', ['$scope', '$stateParams', '$location', 'Authentication', 'Profiles', '$modal', '$log',
function($scope, $stateParams, $location, Authentication, Profiles, $modal, $log) {
this.authentication = Authentication;
// Find a list of Profiles
this.profiles = Profiles.query();
// open a modal window to view single profile
this.modalview = function(size, selectedProfile) {
var modalInstance = $modal.open({
templateUrl: 'modules/profiles/views/view-profile.client.view.html',
controller: function($scope, $modalInstance, profile) {
$scope.profile = profile;
console.log(profile);
$scope.ok = function() {
$modalInstance.close($scope.profile);
};
},
size: size,
resolve: {
profile: function() {
return selectedProfile;
}
}
});
modalInstance.result.then(function(selectedItem) {
$scope.selected = selectedItem;
}, function() {
$log.info('Modal dismissed at: ' + new Date());
});
};
// open a modal window to update single profile
this.modalUpdate = function(size, selectedProfile) {
var modalInstance = $modal.open({
templateUrl: 'modules/profiles/views/edit-profile.client.view.html',
controller: function($scope, $modalInstance, profile) {
$scope.profile = profile;
$scope.ok = function() {
$modalInstance.close($scope.profile);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
},
size: size
});
modalInstance.result.then(function(selectedItem) {
$scope.selected = selectedItem;
}, function() {
$log.info('Modal dismissed at: ' + new Date());
});
};
// Remove existing Profile
this.remove = function(profile) {
if (profile) {
profile.$remove();
for (var i in this.profiles) {
if (this.profiles[i] === profile) {
this.profiles.splice(i, 1);
}
}
} else {
this.profile.$remove(function() {
$location.path('modules/profiles/views/list-profiles.client.view.html');
});
}
};
// Update existing Profile
this.update = function(updatedProfile) {
var profile = updatedProfile;
profile.$update(function() {}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
}
]);
Please suggest me some way, how can i fix this issue? Any help would appreciated.
you can use a directive like this:
<button access-level="canEdit">Edit</button>
and your directive is bound to accessLevel:
angular.module("app")
.directive('accessLevel', ['AuthService', 'AUTH_EVENTS', function (authService, authEvents) {
return {
restrict: 'A',
link: function ($scope, element, attrs) {
var accessLevel;
attrs.$observe('accessLevel', function (acl) {
if (acl) {
accessLevel = acl;
updateCss();
}
});
$scope.$on("auth-change", function (event, data) {
switch (data) {
case authEvents.logoutSuccess:
case authEvents.loginSuccess:
updateCss();
break;
case authEvents.notAuthorized:
default:
}
});
function updateCss() {
if (accessLevel) {
if (!authService.isAuthorized(accessLevel)) {
switch (element[0].nodeName) {
case "A":
element.hide();
break;
default:
element.attr("disabled", "disabled");
break;
}
} else {
switch (element[0].nodeName) {
case "A":
element.show();
break;
default:
element.removeAttr("disabled");
break;
}
}
}
}
}
}
}]);
this is a little bit more than what you need, but gives you an idea what you can achieve. (and you have to write your auth service etc.)
as example here is a part of my auth service:
angular.module('app')
.factory("AuthService", ["$rootScope", "$http", "AuthSession", "AUTH_EVENTS", function ($rootScope, $http, AuthSession, AUTH_EVENTS) {
AuthSession.load();
$rootScope.$on('$stateChangeStart', function (event, nextState) {
if (nextState.data && nextState.data.accessLevel && !service.isAuthorized(nextState.data.accessLevel)) {
event.preventDefault();
$rootScope.$broadcast('auth-change', AUTH_EVENTS.loginRequired, nextState.name);
}
});
var service = {
login: function (credentials) {
return $http
.post('/api/account/login', credentials)
.success(function (data, status) {
if ((status < 200 || status >= 300) && data.length >= 1) {
$rootScope.$broadcast("auth-change", AUTH_EVENTS.loginFailed);
return;
}
AuthSession.create(data.AccessToken, data.User);
$rootScope.$broadcast("auth-change", AUTH_EVENTS.loginSuccess);
}).error(function (data, status) {
$rootScope.$broadcast("auth-change", AUTH_EVENTS.loginFailed);
});
},
logout: function () {
AuthSession.destroy();
$rootScope.$broadcast("auth-change", AUTH_EVENTS.logoutSuccess);
},
isAuthenticated: function () {
return (AuthSession.token !== null);
},
isAuthorized: function (accessLevel) {
if (!accessLevel) return true;
return (this.isAuthenticated() && AuthSession.user.UserRoles.indexOf(accessLevel) !== -1);
}
}
return service;
}]);
this service retrieves a bearer token from the server and stores it in the authsession service. the user roles are also stored beside of other user information. since the backend is also secured, one who changes the user roles on the client, can't write to the backend. (everything on client side is just for the look and feel of the user)
Two ways :
Once the profile is created, let the isProfileCreated (you need to make one) column in user details table be updated. On angular load, call and check whether is profile created. use ng-show to show (edit and delete button)if it is true.
Or else, if you are going to edit, anyways you need to get the profile details from the table. in that case, let your server send a false if no profile is created or an json object if created.
In your controller use
if(angular.isObject(profile)){
$scope.showeditbutton = true;
$scope.showdeletebutton = true;
}
trying to debug something. On our client, we have a Accounts.createUser() call, which include a callback that looks like:
function(err) {
if (err) {
Session.set('entryError', err.reason);
}
else {
return Router.go('/');
}
}
With this setup, a normal signup (i.e. with no errors) works fine. However, if there's an error, the template is destroyed, created, and rendered, twice. I found this question, and went on a hunt for potential reactive variables triggering this. The only thing I can find that changes between the two template destroyed/created/rendered calls is Meteor.loggingIn() (including session variables). That doesn't seem to be causing this, because when I removed all references to it and dependencies on it, the problem continued.
Any pointers?
ETA: per the request below.
signUpPage.html:
<template name='signUpPage'>
<main id="signUpPage">
<h1 class="accountsTitle">Sign Up</h1>
<p id="signInPrompt">If you already have an account sign in.</p>
<form id='signUpForm'>
{{> entryError}}
<div class="form-group">
<label for="usernameInput">Username</label>
<input id="usernameInput" type="string" class="form-control" value=''>
</div>
<div class="form-group">
<label for="emailInput">Email Address</label>
<input id="emailInput" type="email" class="form-control" value=''>
</div>
<div class="form-group">
<label for="passwordInput">Password</label>
<input id="passwordInput" type="password" class="form-control" value=''>
</div>
<div class="form-group">
<label for="confirmPasswordInput">Confirm Password</label>
<input id="confirmPasswordInput" type="password" class="form-control" value=''>
</div>
<div class="form-group">
<label for="signupCodeInput">Signup Code</label>
<input id="signupCodeInput" class="form-control" value=''>
</div>
<button type="submit" class="btn btn-primary btn-block">Sign up</button>
</form>
</main>
</template>
signUpPage.js
Template.signUpPage.events({
'submit #signUpForm': function(event, template) {
event.preventDefault();
// Get the input values from the form
var username = template.find("#usernameInput").value.trim();
var email = template.find("#emailInput").value.trim();
var signupCode = template.find("#signupCodeInput").value;
var password = template.find("#passwordInput").value;
var confirmPassword = template.find("#confirmPasswordInput").value;
// Log the signup attempt
var signupAttempt = {'type':'signup', 'username':username, 'email':email, 'password':password, 'signupCode':signupCode};
Logins.insert(signupAttempt);
// Validate username presence
if (!username.length)
return Session.set('entryError', 'Username is required');
// Validate email presence
if (!email.length)
return Session.set('entryError', 'Email address is required');
// Validate password
var passwordErrors = validatePassword(password, confirmPassword);
if (passwordErrors.length) {
var errorsString = passwordErrors.join("\r\n");
Session.set('entryError', errorsString);
return;
}
// Validate signup code
if (!signupCode.length)
return Session.set('entryError', 'Signup code is required');
Meteor.call('createAccount', username, email, password, signupCode, function(err, data) {
if (err) {
Session.set('entryError', err.reason);
return;
}
else {
Meteor.loginWithPassword(username, password);
return Router.go('/');
}
});
}
});
Template.signUpPage.destroyed = function () {
Session.set("entryError", null);
};
Template.signUpPage.created = function() {
document.title = "Grove OS | Sign Up";
};
The following are js files where entryError is used:
Template.signInPage.events({
'click #signInButton': function(evt, template) {
evt.preventDefault();
// Making lowercase here, check on the server should be case insensitive though
var email = template.find('#emailInput').value.trim().toLowerCase();
var password = template.find('#passwordInput').value;
if (!email.length)
return Session.set('entryError', 'Email is blank');
if (!password.length)
return Session.set('entryError', 'Password is blank');
var loginAttempt = {'type':'login', 'email':email, 'date':new Date()};
return Meteor.loginWithPassword(email, password, function(error) {
if (error) {
loginAttempt.status = 'error';
Logins.insert(loginAttempt);
return Session.set('entryError', error.reason);
} else{
loginAttempt.status = 'success';
Logins.insert(loginAttempt);
return Router.go("/");
}
});
},
'click #signUpButton': function(evt, template) {
evt.preventDefault();
Router.go("signUpRoute");
},
'click #forgotPasswordButton': function(evt, template) {
evt.preventDefault();
Router.go("forgotPasswordRoute");
}
});
Template.signInPage.destroyed = function () {
Session.set("entryError", null);
};
Template.signInPage.created = function() {
document.title = "Grove OS | Sign In";
};
-
Template.resetPasswordPage.helpers({
error: function() {
return Session.get('entryError');
}
});
Template.resetPasswordPage.events({
'submit #resetPasswordForm': function(event, template) {
event.preventDefault();
var password = template.find('#passwordInput').value;
var confirmPassword = template.find('#confirmPasswordInput').value;
// Validate password
var passwordErrors = validatePassword(password, confirmPassword);
if (passwordErrors.length) {
var errorsString = passwordErrors.join("\r\n");
return Session.set('entryError', errorsString);
} else {
return Accounts.resetPassword(Session.get('resetToken'), password, function(error) {
if (error) {
return Session.set('entryError', error.reason || "Unknown error");
} else {
Session.set('resetToken', null);
return Router.go("/");
}
});
}
}
});
Template.resetPasswordPage.created = function () {
document.title = "Grove OS | Reset Password";
};
-
Template.forgotPasswordPage.events({
'submit #forgotPasswordForm': function(event, template) {
event.preventDefault();
var email = template.find("#forgottenEmail").value;
if (!email.length) {
return Session.set('entryError', 'Email is required');
} else {
return Accounts.forgotPassword({
email: email
}, function(error) {
if (error)
return Session.set('entryError', error.reason);
else
return Router.go("/");
});
}
}
});
Template.forgotPasswordPage.created = function () {
document.title = "Grove OS | Forgot Password";
};
-
Router code (combined from 2 files):
//--------------------------------------------------------------
// Global Configuration
Router.configure({
layoutTemplate: 'appBody',
notFoundTemplate: 'notFoundPage',
loadingTemplate: 'loadingPage',
yieldTemplates: {
'appHeader': {to: 'header'},
'appFooter': {to: 'footer'}
}
});
// Have to sign in to access all application pages
Router.onBeforeAction(function() {
console.log("Global router onBeforeAction calle");
// if (!Meteor.loggingIn() && !Meteor.user()) {
if(!Meteor.user()){
this.redirect('/sign-in');
}
this.next();
}, {
// whitelist which routes you don't need to be signed in for
except: [
'signUpRoute',
'signInRoute',
'forgotPasswordRoute',
'signOutRoute',
'resetPasswordRoute',
'pageNotFoundRoute'
]
});
// Subscriptions application-wide
Router.waitOn(function() {
if (Meteor.loggingIn() || Meteor.user())
return Meteor.subscribe("userGroups");
});
//--------------------------------------------------------------
// Root route
Router.route('landingRoute', {
path: '/',
onBeforeAction: function(){
console.log("other global one is being called");
// if (!Meteor.loggingIn() && !Meteor.user()){
if(!Meteor.user()){
this.redirect('/sign-in');
}else{
this.redirect('/grove/dashboard');
}
this.next();
}
});
//--------------------------------------------------------------
// Static Routes
Router.route('/glossary', {
path: '/glossary',
template: 'glossaryPage'
});
Router.route('/eula', {
path: '/eula',
template: 'eulaPage'
});
Router.route('/privacy', {
path: '/privacy',
template: 'privacyPage'
});
Router.route('/about', {
path: '/about',
template: 'aboutPage'
});
Router.route("signUpRoute", {
path: "/sign-up",
template: "signUpPage"
});
Router.route("signInRoute", {
path: "/sign-in",
template: "signInPage"
});
Router.route('signOutRoute', {
path: '/sign-out',
template: "signOutPage",
onBeforeAction: function() {
Meteor.logout();
Router.go('/');
this.next();
}
});
Router.route("forgotPasswordRoute", {
path: "/forgot-password",
template: "forgotPasswordPage",
});
Router.route('resetPasswordRoute', {
path: 'reset-password/:resetToken',
template: "resetPasswordPage",
data: function() {
Session.set('resetToken', this.params.resetToken);
return ;
}
});
Router.route("404Route", {
path: "/page-not-found",
template: "notFoundPage",
});
Router.route("dashboardRoute", {
path: "/dashboard",
template: "dashboardPage"
});
Router.route('createShrub', {
path: '/tools/createShrub',
template: 'upsertShrubPage',
waitOn: function(){
},
data: function () {
},
});
// TODO figure out how to dynamically render templates
// based on if the slug is a group, user, or nothing
// and also conditionally subscribe
Router.route('profileRoute', {
path: '/:ownerSlug',
template: 'myProfilePage'
});
Router.route('groveRoute', {
path: '/:ownerSlug/:groveSlug',
template: 'grovePage',
data: function () {
return Groves.findOne({ slug: this.params.groveSlug });
},
});
Router.route('shrubRoute', {
path: '/:ownerSlug/:groveSlug/:shrubSlug',
template: 'shrubStaticPage',
data: function() {
Session.set("currentShrub", this.params.shrubSlug);
return ShrubTemplates.findOne({ slug: this.params.shrubSlug });
},
action: function() {
if (this.ready())
this.render();
else
this.render('loadingHolder');
}
});
Well, it turned out that as part of the router there was this function:
Router.waitOn(function() {
if (Meteor.loggingIn() || Meteor.user())
return Meteor.subscribe("userGroups");
});
The change in Meteor.loggingIn() caused this function to run, which we saw with our loading page getting displayed briefly. We're changed the if statement so that it no longer contains the Meteor.loggingIn() check. A little embarrassing, really--I swear I looked at that line before. Not sure what happened in my thought process to miss this. At least now I have a better understanding of Iron Router.
In my angular app, i have a message service to display info, loading and error messages for my app. It looks like that:
module.factory('msgSvc', function(){
var current_message = '';
return {
message: function(){
return current_message;
},
setMessage: function(msg){
console.log('setting message: '+ msg);
current_message = msg;
},
clear: function(){ current_message = null; current_style = null}
}
});
and in my view i have
<span class="pull-left label label-warning" >{{ msg.message() }}</span>
I have a login controller, when the user submits the form i want to show a "logging you in..." message while an ajax login is sent. and an error message if there was an error. here's my code:
function LoginCtrl($scope, $http, msgSvc) {
[...]
$scope.login = function(creds) {
console.log(creds);
msgSvc.setMessage('Logging in...');
$http.post('http://...',creds)
.success(function(data){
console.log(data);
[...]
msgSvc.clear();
$location.path('/');
})
.error(function(data, status){
console.log(status);
msgSvc.setMessage('Wrong username or password.');
});
};
}
login() is called by the submit form, Logging in... never shows even though the function is called (it appears in the console). but the error message appears.
am i doing something wrong?
edit: the login form
<form class="form">
<input type="text" placeholder="Username" ng-model="loginCreds.username" required />
<input type="password" placeholder="Password" ng-model="loginCreds.password" required />
<button ng-click="login(loginCreds)">Login</button>
</form>
edit 2
If it changes anything, there are many controllers setting messages in the service and in the actual code, the controller showing the message (where the $scope.msg variable is set) is different from the one setting the message.
function BodyCtrl($scope, msgSvc) {
$scope.msg = msgSvc;
}
There are couple problems with your implementation:
As the message is being set in a private variable, you would need use $watch for the message to be displayed;
A .factory is a singleton and therefore setMessage would have set the same message for all controllers.
The simplest solution is to pass the controller's $scope to the svcMsg:
app.factory("msgSvc", function () {
return function (scope) {
var priv_scope = scope;
this.setMessage = function (msg) {
console.log('setting message: '+ msg);
priv_scope.message = msg;
};
this.clear = function () {
priv_scope.message = "";
};
};
});
In you controller, you would then do:
var msg = new msgSvc($scope);
In case you do want to propagate the message to all controllers, use $rootScope:
app.service("msgSvc", function ($rootScope) {
var priv_scope = $rootScope;
this.setMessage = function (msg) {
console.log('setting message: '+ msg);
priv_scope.message = msg;
};
this.clear = function () {
priv_scope.message = "";
};
});
Check out this Plunker using $rootScope:
http://plnkr.co/edit/NYEABNvjrk8diNTwc3pP?p=preview
As $rootScope is really a global variable in Angular, you shouldn't abuse it. It can also be problematic if you accidentally set the $scope.message in controllers. An alternative is to use $watch to detect the change to the message:
// In your controller, do:
$scope.$watch(
function () {
return msgSvc.message;
},
function () {
$scope.message = msgSvc.message;
}
)
Here is an example using $watch:
http://plnkr.co/edit/vDV2mf?p=info
Set $scope.msg in each place you want to display the value on the view:
function LoginCtrl($scope, $http, msgSvc) {
[...]
$scope.msg = "";
$scope.login = function(creds) {
console.log(creds);
$scope.msg = msgSvc.setMessage('Logging in...');
$http.post('http://...',creds)
.success(function(data){
console.log(data);
[...]
$scope.msg = msgSvc.clear();
$location.path('/');
})
.error(function(data, status){
console.log(status);
$scope.msg = msgSvc.setMessage('Wrong username or password.');
});
};
}
I know you may be trying to avoid that but the changes in its value are not being propagated.
Add $apply to in error()
function LoginCtrl($scope, $http, msgSvc) {
[...]
$scope.login = function(creds) {
console.log(creds);
msgSvc.setMessage('Logging in...');
$scope.msg = msgSvc;
$http.post('http://...',creds)
.success(function(data){
console.log(data);
[...]
msgSvc.clear();
$location.path('/');
})
.error(function(data, status){
$scope.$apply(function() {
msgSvc.setMessage('Wrong username or password.');
});
});
};
}
SEE DEMO