CSS is not working with vue js on dynamic routing - javascript

I created route in vue
{
path: '/coursedetailed/:id',
component: MyCourseDetailed,
props: true
},
It works, but after I go to the page, it seems that css is disabled. All request are completed component if filled with data. There is one error in console. The other pages works well
Uncaught SyntaxError: Unexpected token <
My vue script for component:
<script>
import axios from 'axios'
import MenuWhite from '#/components/MenuWhite.vue'
export default {
name: 'coursedetailed',
props: ['id'],
components: {
MenuWhite
},
data: () => {
return {
course: [],
errors: []
}
},
created () {
this.getData()
},
methods: {
getData () {
axios({
method: 'get',
url: this.$store.state.endpoints.baseUrl + '/api/courses/' + this.$route.params.id + '/',
withCredentials: true,
headers: {
Authorization: `JWT ${this.$store.state.jwt}`,
'Content-Type': 'application/json'
}
}).then((response) => {
this.course = response.data
})
},
isToken () {
if (this.$store.state.jwt) {
this.$router.push({ path: '/profile' })
} else {
this.$router.push({ path: '/' })
}
}
}
}
Any ideas where the problem may be?

Please check this link.
As it says, a basic Vue component may have a template, a script and a style tag.
Inside the style tag you may put your css directly or import your css file using the #import as you can see here by #Geraldine Golong's answer.
So, my suggestion is to put your css code inside your component (if so, recommend you to put inside your parent component), or import your css file using the proper Vue tag.
Hope it helps.

Related

A static web page generated by NUXT has a script error only when it's dynamic routing

I am creating a website on Nuxt.js and experiencing a problem below.
First, I wrote nuxt.config.js as below so a headless CMS works.
export default {
target: "static",
ssr: true,
generate: {
async routes() {
const pages = await axios
.get(
`https://path/to/endpint`,
{
headers: { "XXXX-API-KEY": process.env.API_KEY },
}
)
.then((res) =>
res.data.contents.map((content) => ({
route: `/${content.id}`,
payload: content,
}))
);
return pages;
},
},
    //other settings omitted
And then I prepared a page as "/pages/_id/index.vue" and the code is like below
<template>
<div class="article">
<p>{{ content.title }}</p>
</div>
</template>
<script>
export default {
name: "",
async asyncData({ payload }) {
if (payload) {
return {
content: payload,
};
}
},
};
</script>
In this case, when I start "nuxt start" and preview that page, actually "content.title" is shown on the page successfully, but there is a console error which says "TypeError: Cannot read properties of undefined (reading 'title')". (see the image)
I feel this behavior is weird because nuxt generate should simply generate a static-transpiled files, however this error implies that a vue variable is re-evaluated on the browser...
And when I put exactly the same code on the static routing such as pages/preview/index.vue, this error does not occur.
Does anyone have a clue?
Resolved by myself.
nuxt.config.js shoud be like below
res.data.contents.map((content) => ({
route: `/${content.id}`,
payload: content,
}))
but my code was without slash in "route"
res.data.contents.map((content) => ({
route: `${content.id}`,
payload: content,
}))
didn't understand the difference yet but anyway resolved....

Where to store Laravel Passport "client_secret" in VueJS

I am a bit new to VueJS and I am using Laravel as API only and VueJS as a separate project.
In my App.vue, I have following setup:
http://api.com is my virtual host!
<script>
import axios from 'axios';
export default {
data () {
return {
}
},
created() {
const postData = {
grant_type: "password",
client_id: 2,
client_secret: 'MvEyvm3MMr0VJ5BlrJyzoKzsjmrVpAXp9FxJHsau',
username: 'mail#gmail.com',
password: '**********',
scope: ''
}
axios.post('http://api.com/oauth/token', postData)
.then(response => {
const header = {
'Accept': 'application/json',
'Authorization': 'Bearer ' + response.data.access_token,
};
axios.get('http://api.com/api/user', { headers: header })
.then(response => {
console.log(response.data)
})
})
}
}
</script>
But this file is totally visible to front-end which is not good due to security reasons.
What I did, I made a new route in Laravel as Route::post('get_client_creds', MyController#index); and then made a request from axios as:
axios.post('http://api.com/get_client_creds')
.then(response => {
this.client_secret = response.client_secret;
});
And but then I thought anyone can also access the route using Postman or may be through console using axois, so can someone give me some suggestions about where to store these secrets???
Thanks in Advance!
There are two different ways to specify config settings for vue
#1 Vue.js non-cli projects, you can use src/config.js
Create a new file src/config.js and add as following
export const API_CLIENT_ID = '123654';
To use this, try import like:
import { API_CLIENT_ID } from '../config'
// in your code
console.log(API_CLIENT_ID);
#2 For Vue CLi projects follow these steps.
You must use the .env files hold the configuration variables.
It could be structured like
.env # loaded in all cases
.env.local # loaded in all cases, ignored by git
.env.[mode] # only loaded in specified mode
.env.[mode].local # only loaded in specified mode, ignored by git
Here is how you can specify the variable.
FOO=bar
API_CLIENT_ID=123456
And you can use this as:
console.log(process.env.API_CLIENT_ID)
Please follow the documentation for more details.
https://cli.vuejs.org/guide/mode-and-env.html#environment-variables

Using API JSON data in react conditional return

I have a small (never for production) Express/React app, I'm validating a hashed pin in express and returning either message: false if validation fails or message: <cardnumber> if validation is succefull. In my react frontend I want to eventually redirect if it returns a cardnumber, but first I'm just trying to conditionally render a component.
I have a constructor for the json response
constructor() {
super();
this.state = {
cardnumber: '',
pin: '',
servercardnumber: {
message: ''
}
};
Then I'm getting the data from API like this
const url = '/api/login';
const serverResponse = await fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify(data)
});
const json = await serverResponse.json();
console.log(json);
this.setState(
prevState => {
return {
servercardnumber: json.cardnumber
};
},
() => {
console.log(this.state.cardnumber);
}
);
};
Then I'm trying to conditionally render a material ui component in my react return
render() {
const { cardnumber, pin, servercardnumber } = this.state;
return (
<React.Fragment>
<Card>{!servercardnumber ? <Card> Server says no</Card> : null}</Card>
{console.log('server says:')}
{console.log(servercardnumber)}
The {console.log(servercardnumber)} first returns the correct servercardnumber, then returns undefined.
What I need is to see the response in my conditional render, and show the rendered component if login is succefull (or show if not succefull, as long as I get it to conditionally render)
I've done a bunch of changes to this code in my attempt to get this to work, so it may seem a bit cluttered.
Full front end code for the relevant file: https://pastebin.com/VbdzmE4E
Server code for the relevant file: https://pastebin.com/TZ35NZxa
Reposting my comment here so that it the question can be resolved.
The state property servercardnumber should be set to json.message instead of json.cardnumber.

Axios returns undefined in nested Vue JS (Laravel API)

I'm having a lot of trouble with Axios when using nested routes in Vue JS.
I have found that if my component is at the root ("/"), as with the "Accounts" component below, then Axios loads the data correctly, no problems here.
But if I went to the "Campaigns" component, which is nested at "/accounts/:account_id" then Axios stops working. In fact, it doesn't return any data at all. However, the API is valid, as Postman correctly returns the data.
So whenever I move a component into a nested URL, Axios stops working. I have no idea why this is happening, and I cannot find any solutions online. I'm sure it must be simple, but I can't see it.
app.js (Includes routes)
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
name: 'accounts',
component: Accounts
},
{
path: '/accounts/:account_id',
name: 'campaigns',
component: Campaigns
},
],
});
Campaigns Component
<script>
import axios from 'axios'
export default {
data() {
return {
accountID: null,
campaigns: [],
campaignsMeta: {},
};
},
mounted() {
this.accountID = this.$route.params.account_id;
this.fetchCampaigns();
},
methods : {
fetchCampaigns(page = 1) {
const AuthStr = 'Bearer '. concat(this.apitoken);
axios.get("api/account/" + this.accountID + "?page=" + page)
.then(({data}) => {
this.campaigns = data.data;
this.campaignsMeta = data.meta;
});
}
},
}
</script>
For anyone who is experiencing a similar problem in the future, I made the error of using a relative URL and not an absolute URL for the Axios Get request.
Original Code
axios.get("api/account/" + this.accountID + "?page=" + page)
.then(({data}) => {
this.campaigns = data.data;
this.campaignsMeta = data.meta;
});
Correct Code
axios.get("/api/account/" + this.accountID + "?page=" + page)
.then(({data}) => {
this.campaigns = data.data;
this.campaignsMeta = data.meta;
});
Note the "/" at the start of "/api/account" indicating an absolute path, not relative.
The reason this is important is because:
For relative URLs, the API request would be appended to the end of the current page URL, so the API request on the Accounts component would have been: /accounts/:account_id/api/account (which is wrong!)
For absolute URLs, the API request is made from the domain name, so the API request on the Accounts component is: domain.com/api/account (correct!)
Thanks!

Vue-router 2 changes route but does not update the view?

I have a login issue with website that uses:
Vue.js v2.0.3
vue-router v2.0.1
vuex v0.8.2
In routes.js I have a simple interceptor setup
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!router.app.auth.isUserLoggedIn) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // make sure to always call next()!
}
})
And in login.vue,which handles the login page logic after using Google API only for login succeeds I call this:
this.login(userData).then(
() => this.$router.push(this.redirectToAfterLogin), // Login success
() => {} // Login failed
)
mounted: function(){
if (this.auth.isUserLoggedIn){
// Let's just redirect to the main page
this.$router.push(this.redirectToAfterLogins)
}else{
Vue.nextTick(() => {
this.loadGooglePlatform()
})}}
computed: {
redirectToAfterLogin: function() {
if (this.$route.query.redirect){
return this.$route.query.redirect
}else{
return '/'
}
}
}
router.js
var VueRouter = require('vue-router')
// Router setup
export const router = new VueRouter({
linkActiveClass: "is-active",
mode: 'history',
saveScrollPosition: true,
routes: [
{ path: '', name: 'root', redirect: '/home' },
{ path: '/login', name: 'login', meta: { loadingNotRequired: true }, component: require('./pages/login.vue') },
{ path: '/logout', name: 'logout', meta: { loadingNotRequired: true }, component: require('./pages/logout.vue') },
{ path: '/home', name: 'home', title: 'Home', redirect: '/home/random', component: require('./pages/home.vue'),
children: [
{ path: 'random', name: 'random', meta: { requiresAuth: true }, title: 'Random', component: require('./pages/random.vue') }
]
}
]
})
// Redirect to login page if not logged In
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!router.app.auth.isUserLoggedIn) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // make sure to always call next()!
}
})
Now here this.login is just the call to vuex, to update the logged in user.
What happens is that after login, URL changes to /home, but the DOM does not update!
Only way that successfully changed the DOM was forcing location.reload() and that is not what I want to do, as it loses my dynamically loaded G scripts in Head.
Any idea on what to do to force the view to update DOM?
NOTE: it happens only on the first login of user, if he logs out and back-in, the redirecting is fine
Not a perfect solution may be, as it is going to recreate the component but it will work for every case when having same route & needs to update the component.
Just update the <router-view/> or <router-view></router-view> with
<router-view :key="$route.fullPath"></router-view>
Vue re-uses components where possible. You should use beforeRouteUpdate to react to a route switch that uses the same component.
I have the same problem "URL changes to /home, but the DOM does not update".
In my project, the tag "transition" maked the problem.
Hope it is helpful!
Maybe you should set the redirectToAfterLogin function into methods, like this it will be recalculated each times. The computed will be modified only if used v-model changed. To stick to the meaning of the function name, I would set the router push inside.
login.vue :
mounted: function(){
if (this.auth.isUserLoggedIn){
// Let's just redirect to the main page
// this.$router.push(this.redirectToAfterLogins)
this.redirectToAfterLogins()
}else{
Vue.nextTick(() => {
this.loadGooglePlatform()
})
}
},
// computed: {
methods: {
this.login(userData).then(
// () => this.$router.push(this.redirectToAfterLogin), // Login success
() => this.redirectToAfterLogin(), // Login success
() => {} // Login failed
),
redirectToAfterLogin: function() {
if (this.$route.query.redirect){
// return this.$route.query.redirect
this.$router.push(this.$route.query.redirect)
}else{
// return '/'
this.$router.push('/')
}
}
}
https://v2.vuejs.org/v2/guide/computed.html#Computed-Properties
https://v2.vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods
"However, the difference is that computed properties are cached based on their dependencies. A computed property will only re-evaluate when some of its dependencies have changed. This means as long as message has not changed, multiple access to the reversedMessage computed property will immediately return the previously computed result without having to run the function again."
methods vs computed and filters :
Access vue instance/data inside filter method

Categories

Resources