Here is my login function on my vue js app, works very well on my computer, but on iphone mobile browsers, the "alert('click after')" doesn't work, anything inside then promise callback don't work. Why's that?...
login(){
alert('clicked before')
// this.isLoading = true
User.login(this.logindata).then((result)=> {
alert('clicked after')
localStorage.setItem("token", result.data['access_token'])
this.isLoading = false
// this.$router.push('dashboard')
window.location.href = 'dashboard'
User.auth().then((result)=>{
localStorage.setItem("auth", "true")
})
}
).catch((err) => {
if(err.response.data.errors['email']){
this.message = err.response.data.errors['email'][0]
}else{
this.message = err.response.data.errors[0][0]
}
});
}
Related
I'm trying to use 'router.beforeEach' for checking token.
chrome can enter in beforeEach, but safari couldn't.
is there anything I have to know before use 'beforeEach' in safari?
I'm so confused and this problem makes me crazy.
here is code. there are meta : {authRequired: true} every components except login component.
router.beforeEach(function (to, from, next) {
console.log("I'm in!!!")
let token = VueCookies.get('jwtToken');
let isAuthenticated = token !== null;
if (to.matched.some(function(routerInfo) {
return routerInfo.meta.authRequired;
})) {
if(!isAuthenticated) {
if(to.name != 'login') {
next({name: 'login'});
}
}else {
next();
}
}else {
next();
}
})
Google Chorme
Safari so---------clean....
can I use beforeEach in safari?
This works for me if the user isn't logged in, however the else if wont work at all even though the route path is "/login" and main.authState is true. How do I set this up properly?
router.beforeEach((to, from, next) => {
const main = useAuthStore(router.pinia);
if (to.matched.some((record) => record.meta.authRequired)) {
if (!main.authState) {
return next("/login");
}
} else if(to.matched.some((record) => !record.meta.authRequired)) {
if (to.path == "/login" && main.authState == true) {
alert(to.path) //"/login"
alert(typeof(main.authState)) //"boolean"
return next();
}
}
next();
});
async signOut() {
await auth.logout();
await localStorage.removeItem("authenticated");
await router.replace({ name: "Login" });
},
If auth is not required for some route, you should not check for authState.
If I didn't understand correctly, explain.
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.authRequired)) {
const { authState } = useAuthStore(router.pinia);
// Ensure what authState is true to proceed to next() route
authState
? next()
: next('/login');
} else {
next();
}
});
You could use a URL query param to store the redirect target, which you then access from your Login.vue component, and can set a default value to redirect to when the user accesses the /login route as an authenticated user without a predefined redirect.
router.beforeResolve(async (to, from, next) => {
if (to.matched.some((record) => record.meta.authRequired)) {
const lastMathcedRoute = to.matched[to.matched.length - 1].path || "/";
// "/" is just a fallback route
const main = useAuthStore(router.pinia);
const isAuthenticated = main.authState;
if (!isAuthenticated ) {
next({ path: "/login", query: { redirect: lastMathcedRoute } });
} else {
next();
}
} else {
next();
}
});
And then in your Login component, you just access the redirect query param if user is already authenticated or when his auth state changes. Basically you need to somehow be notified, or watch the auth state and redirect the user accordingly. So you need authState to be a ref or reactive object that you can watch.
// Login.vue
import { useRouter } from "vue-router";
setup() {
const router = useRouter();
const { authState } = useAuthStore(router.pinia);
watch(authState, () => {
if (authState) {
const redirectLocation = route.query?.redirect?.toString() || '/pannel';
// here '/panel' is the default redirect
return router.push(redirectLocation);
}
}, { immediate: true } )
}
PRO Tip: notice { immediate: true }, this makes it so that the watch immediately fires with the initial value of the authState, instead of firing just when it changes. This is helpful in the case that the authState is already true and it does not change.
You can use other mechanisms instead of a watcher, but in principle the solution is the same.
I've try use axios request in web worker by vue plugin
My code looks like this:
//worker.js
import axios from 'axios';
export default function getApiData(args) {
axios.get('/api/test').then(response => {
console.log(response);
});
}
And main file with Vue
//main.js
import getApiData from './worker.js';
Vue.use(VueWorker);
window.vueApp = new Vue({
//...
created: function() {
this.updateWorker = this.$worker.create([
{
message: 'getApiData ',
func: getApiData
}
]);
this.testWorker.postMessage('getApiData ', [this.args])
.then(result => {
console.log(result);
})
},
//...
}
And I got this error
Uncaught ReferenceError: axios__WEBPACK_IMPORTED_MODULE_0___default is
not defined
What I'm doing wrong?
I had the same problem and solved it by going back to the basics - using plain old XMLRequest (see below).
You can't use axios inside the worker because the blob that's created behind the scenes to load the worker.js runs in a different context than your main.js. In order for axios to work, you would have to setup a new webpack bundler to just bundle the worker by itself. I didn't want to do that - it makes the project structure unnecessary complex.
Here is a simple solution (works with json and non-json response).
// worker.js
export default () => {
self.addEventListener('message', e => {
if (!e) return;
// wrap in try/catch if you want to support IE11 and older browsers
// that don't support Promises. The implementation below doesn't work
// even when polyfills are loaded in the main project because
// the worker runs in a different context, ie no webpack bundles here.
try {
const fetchData = (url, isJSON = true) => {
return new Promise((resolve, reject) => {
function reqListener() {
if (this.status !== 200) {
return reject();
}
const response = isJSON
? JSON.parse(this.responseText)
: this.responseText;
resolve(response);
}
const oReq = new XMLHttpRequest();
oReq.addEventListener('load', reqListener);
oReq.open('GET', url);
oReq.send();
});
};
const baseUrl = 'https://static.newsfilter.io/';
const { articleId } = e.data;
const jsonUrl = baseUrl + articleId + '.json';
const htmlUrl = baseUrl + articleId + '.html';
// My use case requires 2 requests in parallel.
const tasks = [fetchData(jsonUrl), fetchData(htmlUrl, false)];
Promise.all(tasks)
.then(data => {
postMessage({ json: data[0], html: data[1] });
})
.catch(error => {
postMessage({ isError: true, error });
});
} catch (error) {
postMessage({ isError: true });
}
});
};
I am using react-native-linkdin-login library to support linkding sigin in my application.It is working properly in android but in iOS it always ask to download an application rather than application already exist in device and redirect to the APP store. When I open and login to linkdin account, I can't come back to my react-native application, with user profile details.
Give me any suggestion as soon as possible.
async componentWillMount() {
LinkedinLogin.init(
[
'r_emailaddress',
'r_basicprofile'
]
);
}
async handleLinkedinLogin(){
LinkedinLogin.login().then((user) => {
alert("linkdin");
this.setState({ user : user });
this.getUserProfile();
}).catch((e) => {
var err = JSON.parse(e.description);
alert("ERROR: " + err.errorMessage);
alert('Error', e);
});
return true;
}
getUserProfile(user) {
LinkedinLogin.getProfile().then((data) => {
const userdata = Object.assign({}, this.state.user, data);
this.setState({ user: userdata });
const Email = userdata.emailAddress;
const Fullname = userdata.firstName+' '+userdata.lastName;
const SocialAppId = userdata.id;
const SignupType = 'Linkedin';
alert("Please wait....")
this.socialLogin(Fullname,Email,'null',SignupType);
}).catch((e) => {
alert(e);
});
}
I have a website with a login form. If a user is not logged and tries to access a internal page it will be redirected to the default page. For instance if I try to access
http://siteURL.PhantomPrint.aspx I will be redirected to http://siteURL/Default.aspx?ReturnUrl=PhantomPrint.aspx. And after login an automatic redirect will take place to the page.
After the redirect I want to render the page with Phantomjs and save it as pdf. The problem is that the rendering takes place before page load is finished and I can properly render the page only if I use timeouts. In this case, if the page loading takes longer than normal the resulted pdf is not the proper one.
Below you can find the java script code:
var page = require('webpage').create();
var index = 0,
page.onConsoleMessage = function (msg) {
console.log(msg);
};
var steps = [
function () {
//Load Login Page
page.open("http://siteURL.PhantomPrint.aspx", function () {
//Enter Credentials
page.evaluate(function () {
console.log("filling inputs");
var usernameInput = document.getElementById("txtUsername");
usernameInput.value = "user";
var passwordInput = document.getElementById("txtPassword");
passwordInput.value = "password";
var loginButton = document.getElementById("btnLogin");
loginButton.click();
console.log("login button was submitted");
});
});
},
function () {
// page.onLoadFinished = function () {
// Render the page to pdf
page.render('example.png');
phantom.exit();
console.log("rendering finished");
//});
}
];
interval = setInterval(function () {
if (!loadInProgress && typeof steps[testindex] == "function") {
console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] != "function") {
console.log("test complete!");
phantom.exit();
}
}, 1000);
Any suggestions on how I can assure that rendering is done only after the redirected page is finishing loading are welcomed.
It looks like you want to process navigation steps. You would need to use page.onNavigationRequested to pick up if a page load/redirect was issued. This will be likely hard to maintain. You would also have to discard the idea of using a step array with setInterval.
Another possibility would be to specifically wait for some selector that is present in the target page using waitFor, but then again, this would make the use of setInterval impossible.
CasperJS is actually built on top of PhantomJS and uses steps to navigate the site. When you use any of the then* functions it will automatically pick up a page load and wait for page load finish until executing the callback.
var casper = require('casper').create();
casper.on("remote.message", function (msg) {
console.log(msg);
});
casper.start("http://siteURL/PhantomPrint.aspx", function () {
//Enter Credentials
this.evaluate(function () {
console.log("filling inputs");
var usernameInput = document.getElementById("txtUsername");
usernameInput.value = "user";
var passwordInput = document.getElementById("txtPassword");
passwordInput.value = "password";
});
this.click("#btnLogin");
this.echo("login button was submitted");
});
casper.then(function () {
this.capture('example.png');
});
casper.run();
This can be made even smaller by using casper.fillSelectors.
After more research I found a solution, see below code.
var loadInProgress = false;
page.onLoadStarted = function () {
loadInProgress = true;
console.log("load started");
};
page.onLoadFinished = function () {
loadInProgress = false;
console.log("load finished");
};
interval = setInterval(function () {
if (!loadInProgress && typeof steps[testindex] == "function") {
console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] != "function") {
console.log("test complete!");
phantom.exit();
}
}, 100)
But I would like to know if there is no other solution which would not involve recursively function calling.