UI-Router: Change url without loading state or defer loading the state? - angular-ui

I'm using angular-ui's UI-Router in my project and on state change I want to check if the user has access to the page. If not I popup a login modal.
$rootScope.$on('$stateChangeStart', function(evt, toState) {
if (!authentication.authorize(toState.data.access)) {
evt.preventDefault();
$state.go('login', {}, {notify: false});
}
});
The login state, using a modal from UI-Bootstrap:
angular.module('components.security').config(function($stateProvider) {
$stateProvider.state('login', {
onEnter: function($state, $modal) {
$modal.open({
templateUrl: "/components/security/login.html",
controller: 'LoginCtrl as controller'
});
}
});
});
It's working perfectly fine on the first page load: The ui-view isn't rendered, the login modal pops up, and when the user logs in I call $urlRouter.sync(); and the view is loaded.
However, if you navigate from page to page this is what should happen:
User is on /pageA, clicks a link to /pageB (which he doesn't have access to)
Url changes to /pageB
The ui-view is not loaded, instead the login modal pops up
After login is complete the modal closes, ui-view loads
Instead what happens is this:
User is on /pageA, clicks a link to /pageB (which he doesn't have access to)
Url stays at /pageA
Login modal pops up
After login is complete the modal closes, but you're still on page A.
So what I'd really like is that the url actually changes to /pageB but the ui-view doesn't load until you call sync.

Have you considered saving toState and angular.copy(toParams) in your authentication $stateChangeStart listener, then triggering $state.go after the user has logged in?
The URL is not set to /pageB when the user transitions there because when you preventDefault, the transition is prevented (and the url is reset to pageA):
if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams).defaultPrevented) {
syncUrl();
return TransitionPrevented;
}

Related

Protect the unauthenticated route in next js

I'm newly start on next js project , we have added a middlewate in next js to protect the route like below
useEffect(() => {
if (typeof window !== undefined) {
if (router.pathname == "/reset-password") {
// allow before login
}else if (!loginUser.authenticated) {
router.push('./login')
}
else if (loginUser.authenticated && !loginUser.selectedCustomer) {
router.push('./search-customer')
} else if (loginUser.authenticated && loginUser.selectedCustomer) {
if (router.pathname == "/") {
router.push("/stock-items/categories");
}
}
}
}, []);
return <>{props.children}</>;
But the issue is when any one direclty hit the specific route the controller goes to specific page and then nevigate to login screen if user is not login
i'm trying to stop that type of process , if user is not login then then any route should not be nevigate
please help us
useEffect runs on the client-side after the DOM has rendered (the typeof window check is therefore unnecessary).
This means any checks you place in the useEffect will be ran after the user see's the page (even just for a split second).
There are 2 options how you can handle this. Both are mentioned in the authentication guide in NextJS docs. I recommend taking a look.
Option 1
Set loading state default state as true, rendering a loading indicator while you do your authentication checks...
After you finish authenticating, toggle the loading state to false, allowing to render the page.
Option 2 (Recommended)
What you want to do here is take advantage of Next's core features such as getServerSideProps.
The code you put into getServerSideProps runs BEFORE the client receives any HTML payload.
In the getServerSideProps you can do your authentication, check for authentication cookie or Authorization header, depends what authentication method you use, and either redirect the user to /login page.

Displaying form on first login

I'm trying to work out how I can display a form to a user upon their first login to my app ( to fill in profile information) after which they can proceed to the regular site.
Could anyone point me in the right direction?
Thanks
You can make the trick using app startup script:
https://devsite.googleplex.com/appmaker/settings#app_start
Assuming that you have Profile model/datasource, code in your startup script will look similar to this:
loader.suspendLoad();
var profileDs = app.datasources.Profile;
// It would be more secure to move this filtering to the server side
profileDs.query.filters.UserEmail._equals = app.user.email;
profileDs.load({
success: function() {
if (profileDs.item === null) {
app.showPage(app.pages.CreateProfile);
} else {
app.showPage(app.pages.HomePage);
}
loader.resumeLoad();
},
failure: function() {
loader.resumeLoad();
// your fallback code goes here
}
});
If profile is absolute must, I would also recommend to enforce the check in onAttach event for every page but CreateProfile (to prevent navigation by direct link):
// Profile datasource should be already loaded by startup script
// when onAttach event is fired
if (app.datasources.Profile.item === null) {
throw new Error('Invalid operation!');
}
I suggest checking the user profile upon login. If the profile is not present, display the profile form, otherwise, proceed to the regular site.

Change action in Contact Form 7

Would modify the action of Contact Form 7 once sent the mail.
I follow this post and woks fine. But my fom is in a Bootstrap Modal, and I wish they would keep open on submit.
My code is.
In function PHP
add_filter('wpcf7_form_action_url', 'wpcf7_custom_form_action_url'); function wpcf7_custom_form_action_url() { return 'http://saviacomunicacion.com.ar/test2014#sala-de-prensa'; }
And in the Aditional Settings field
add_filter('wpcf7_form_action_url', 'wpcf7_custom_form_action_url');
This redirect the URL, but it´s not sending the mail.
I wish i could send the mail and keep the modal open to show the response: Your mail was send correctly.
Thanks
According to the doc there is another way to accomplish the redirect. Just add some piece of code to the plugin dashboard.
Or you can do custom js function
in the plugin options
on_sent_ok: "customFunction();"
and somewhere in the code
<script>
function customFunction() {
// show your modal here
$('#myModal').modal();
}
</script>
I found my solution with this code. When form submit, the Modal closes after 1 second.
Instead of keeping Modal open, i wait 1 second after close, to show the response of the sending.
j(".form-horizontal").live("submit", function(){
j.post(this.action, j(this).serialize(), function(){
//this callback is executed upon success full form submission close modal here
}, "script");
//this is to wait 1 second until close
setTimeout(function() {j('.modal').modal('hide');}, 1000);
return false;
});

How do I get onRendered to run a second time when the route changes but the template remains the same?

I have an iron-router route for updating the data of a specific project:
Router.route('/project/:key/update', {
...
});
Each time the user navigates to an "edit project page" I want to focus the project-name input.
template.onRendered(function() {
this.$('form input[name="project_name"]').focus();
});
This works great when navigating from the Dashboard to any given edit project page. However, navigating to/from one project page to another the onRendered function doesn't rerun and consequently the input is not focused.
You can force onRendered to reevaluate after a context change by adding a check for currentData inside of an autorun like this:
Template.myTemplate.onRendered(function() {
var self = this;
this.autorun(function() {
// hack to force the autorun to reevaluate
Template.currentData();
// insert onRendered code here
self.$('form input[name="project_name"]').focus();
});
});
For more details, see the end of this issue.

Session variable resetting between pages

I'm learning Meteor and I'm trying to use the counter example with Iron Router.
Everything is working in the counter page and the routes too, except that when I'm navigating between pages and come back to the counter page, the counter resets to 0 (after I've clicked and incremented the counter).
The HTML is:
<template name='counter'>
<button>Click Me</button>
<p>You've pressed the button {{counter}} times.</p>
</template>
and the javascript is:
Session.setDefault("counter", 0);
Template.counter.helpers({
counter: function () {
return Session.get("counter");
}
});
Template.counter.events({
'click button': function () {
Session.set("counter", Session.get("counter") + 10);
}
});
I tried to put
Session.setDefault("counter", 0);
inside a template.counter.rendered/template.counter.created but it's the same.
Does anyone knows how to guarantee that session values can be preserved?
It seems that everything is working as expected and it was my problem: as I was trying to test dynamic routes, sometimes I changed the URL manually on the browser instead of using the "go back" button or navigate using my own page links.
And, as it is supposed, by doing that I'm refreshing the page, and everytime I refresh a page I loose session values...
Hope this could be useful to someone else.

Resources