I've got a polymer starter kit app with several sub routes and various types of records associated with those routes. An example URL might be //myapp/records/{recordId}/subRoute. I would like the app state to persist on reload. I've tried like so:
<app-route
route="{{route}}"
pattern="/records/:recordId"
data="{{routeData}}"
tail="{{subroute}}"
></app-route>
<app-route
route="{{subroute}}"
pattern="/:page"
data="{{subRouteData}}"
></app-route>
<firebase-document
id="recordsDocument"
path="/records/[[routeData.recordId]]"
data="{{record}}"
></firebase-document>
...
<script>
routePageChanged(page) { // takes subRouteData.page
if (!user) {
set('page', 'login'),
} else if (!routeData.recordId) {
set('page', 'start')
} else {
set('page', page)
}
}
</script>
But under these conditions, the browser will always end up on the login page, since routePageChanged is called before firebase responds with the user.
How can I get my app to correctly load from address bar routes that depend on the existence of an auth'd firebase user when that object does not exist until firebase responds?
You can do several things. Since you are waiting for the user, you need the user object to be initialized.
In firebase-auth, there is a user object:
user: {
type: Object,
readOnly: true,
value: null,
notify: true
},
You could listen for changes on that object.
An alternative way is to handle it like this:
this.$.auth.signInWithPopup()
.then(function(response) {// successful authentication response here})
.catch(function(error) {// unsuccessful authentication response here});
On success of above code, the user object should be set, you could check your initial routing with that.
I can't think of any other options on top of my head.
Other then that, I have to recommend the docs, ofcourse :P
https://github.com/firebase/polymerfire/blob/master/firebase-auth.html
Related
const router = new VueRouter({
routes: [
{path: '*', redirect: '/'}
}
)}
I have set this as redirect route in routes.js file.
how i can set more than 1 redirect path and call it on particular condition
In the component you want to set multiple redirects based on a condition you can use beforeRouteEnter() property in that component like below:
beforeRouteEnter(to,from,next){
next(vm => {
if(condition 1){
vm.$router.push('the path you want to redirect');
}else if(condition 2){
vm.$router.push('the path you want to redirect');
}else{
//no redirect
next();
}
});
}
Since the vue instance is not yet created when beforeRouteEnter() property is called you cannot use this to access the vue instance and follow the process the method shown above via vm
Another way would be by using route meta feilds where you would include a meta field when defining a route and checking for a meta field in the global navigation guard. In that global navigation guard you can redirect by checking various if statements.
Here is a screenshot from their docs about <Link> component
What state do they mean? A Redux state?
How does it look like to pass a state? Like this?
pathname: '/foo',
query: {
x: this.props.x,
},
state: store.getState()
It's a piece of information that you'd like to send to the next page. Nothing to do with Redux. It's a plain object. I believe Flipkart is a very nice example of how it can be used to improve user experience:
Go to a Flipkart search page on a mobile device (or simulate one using Chrome DevTools)
Tap on one of the items
You'll see that the transition happens instantly and pieces of information like product images, title, rating and price are readily available on the product page. One way to implement that is passing the state they had already loaded on the search page onto the next one:
<Link
to={`/product/${id}`}
state={{
product,
}}
/>
And then:
function ProductPage(props) {
// Always check because state is empty on first visit
if (props.location.state.product) {
console.log(props.location.state.product);
// { id: '...', images: [...], price: { ... } }
}
}
There are two ways to pass data from one route to another via Link.
URL Parameter.
As state.
URL parameter help when the route params contain strings for example we want to route to a particular profile:
<Link to='/azheraleem'>Visit Profile</Link>
However, the later i.e. the state helps us pass data from one route to another which is complex data structure. (objects/arrays).
As per the react router documentation, in case of passing data from one route to another it can be done as per the below code sample:
<Link
to={{
pathname: "/profile",
search: "?name=azheraleem",
state: { fromDashboard: true }
}}
/>
The pathname is the link to the route while the search attribute contains the query string parameters, thus the on clicking the link the URL will form something like:
http://localhost:3000/profile?name=azheraleem.
But the state variable value can be accessed in the called route using the useLocation hook:
import { useLocation } from "react-router";
const profile() => {
let data = useLocation();
console.log(data.state.fromDashboard);
}
The the state property of the to prop is the param of pushState method of History DOM object described here
That props used in push/replace methods of router as described here for transitions to a new URL, adding a new entry in the browser history like this:
router.push('/users/12')
// or with a location descriptor object
router.push({
pathname: '/users/12',
query: { modal: true },
state: { fromDashboard: true }
})
It also mentioned here:
router.push(path)
router.push({ pathname, query, state }) // new "location descriptor"
router.replace(path)
router.replace({ pathname, query, state }) // new "location descriptor"
state is a property that's part of the object you can provide to the to prop of the <Link> component.
It is particularly useful if you want to send data from the current view to one the <Link> directs you to, without using common techniques such as setting URL parameters or using libraries, such as Redux.
There isn't much official information about the state key, but here's what I found in the source code of that component:
Links may pass along location state and/or query string parameters
in the state/query props, respectively.
So basically, it's like sending props to a component from a parent. Here, you are sending "state" from the current view to the target view. That's about it, really.
In simple term state in <Link/> component is use to pass information from one view to other view through router in form of object.On other page it can be access using prop.location.state.
(Note: on browser refresh state no longer contain information)
To pass state in Link:
<Link to={{pathname: "/second_page", state: {id: 123}}} />
To access id in second page view:
let id = props.location.state.id;
For more Link properties : React Router Link
I am working on a project in which I have to login a BasicAuth website. I come across the document of webRequest and realize there are three different onAuthRequiredOptions: namely "responseHeaders", "blocking", "asyncBlocking".
I have tried them and the only thing I found out is that with "asyncBlocking", Chrome will let the extension has a chance to fire a callback, which can authenticate the BasicAuth, change the request header, e.t.c..
chrome.webRequest.onAuthRequired.addListener(
function(details, callback) {
callback({
authCredentials: {username: "login", password: "login"}
});
},
{urls: ['<all_urls>']},
['asyncBlocking']
);
But with "responseHeaders", "blocking", their behaviors seems to be the same, they both DO NOT have callback, but then I couldn't figure out the other differences.
I believe there is a reason for separating into three values. So I would like to know what is the philosophy behind them?
Thank you.
The responseHeaders permission is used to populate the optional property of details and is available in a couple of the methods. Without this permission, the headers that are received aren't available to the webRequest handler. As for blocking and asyncBlocking they are the same except one is synchronous and the other is not. asyncBlocking allows you to specify a callback like in your example, while blocking expects a return in the handler itself like so:
chrome.webRequest.onAuthRequired.addListener(function(details) {
return {authCredentials: {username: "login", password: "login"}};
},
{urls: ['<all_urls>']},['blocking']);
I am trying to implement simple authentication with react-router. I think there is an issue with replace and callback. Consider following code:
1) Routing configuration
function getRoutes() {
return {
path: "/",
indexRoute: require("./Home"),
component: require("./Shared/Layout"),
onEnter: handleEnter,
childRoutes: [
require("./Login"),
require("./Secured"),
require("./Any")
]
}
}
function handleEnter(nextState, replace, callback) {
let state = store.getState()
if (!state.hasIn(["shared", "user"])) {
store.dispatch(fetchUser())
.then(callback)
}
}
2) ./Secured route configuration
export = {
path: "/secured",
component: require("./Secured"),
onEnter(nextState, replace) {
let state = store.getState()
if (!state.getIn(["shared", "user"])) {
replace("/login")
}
}
}
It should work like this:
Fetch user when entering root route (async operation, we need callback)
Go to /secured and check whether user is authenticated when entering the route
If user is not authenticated go to /login
The problem is that the /login page will not be rendered. The URL is changed to /login, but nothing is displayed and there are no error messages in console. When I remove callback parameter from the root route configuration, it starts working as expected.
Am I doing something wrong?
Well, it was really stupid :) I've forgot to call callback when user is already authenticated.
I am looking to perform multiple actions upon receiving HTML(or EJS) form content using the POST method. I am using Node express, mongoose & mongoDB. Each of the below POST responses work individually but i am unsure how to proceed in updating multiple databases based on ONE SINGLE form submission.
// insert into passport db
app.post('/signup', passport.authenticate('local-signup',
{
successRedirect : '/index', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
//insert into my database here
[the content of in the second function is unimportant as that is working fine and has been stripped down for simplification.]
app.post('/signup', function( req, res )
{
new UserDB(
{
user_id : req.body.content,
first_name : req.body.fname,
}).save( function( err, mySite, count )
{
res.redirect( '/index' );
});
});
I have tried redirecting but the form content is not accessible after the redirect so only the first function stores the data (ie. only 1 database is filled).
How would i run both functions within
app.post('/signup',.....
{
...
});
?
Thanks in advance!
You can do this by making one function the callback of the other. This is easy because each function maintains the same Connect middleware signature, function(req, res, next), where req and res are the request and response objects created and manipulated by the application, and next is the next function to call at the end of the current function's execution.
According to the official documentation, passport.authenticate() is a normal piece of middleware. All you need to do is specify the middleware you want to be called next. Express queues middleware functions in the order in which you pass them into app.post. You can do something like this:
app.post('/signup', passport.authenticate('local-signup', {
failureRedirect : '/signup',
failureFlash : true
}),
function(req, res) {
new UserDB({
user_id : req.body.content,
first_name : req.body.fname,
}).save(function(err, mySite, count) {
res.redirect('/index');
});
});
Middleware is an extremely powerful feature of the Express framework and possibly the single most important one to master. This guide would be a great next step if you want to learn more.