v-html of Vue doesn't support promise,etc,all of vue binding value doesn't support promise,is there a solution? - vue.js

code in my project
the formatter method, may include async method, and may be use async and await,when i use, page render uncorrectly。Is there a solution?

Welcome to Stackoverflow. Please do not send code in images, as this is very inconvenient to answer. And please do not add links to external pages unless it is an official documentation.
Vue only binds variables which are defined in the data section.
So this should work:
export default {
data() {
return {
scope: {
data: {row: []}
but this will not bind the row records:
export default {
data() {
return {
scope: {} // does not work with scope.data.row

Related

How do I properly import multiple components dynamically and use them in Nuxt?

I need to implement dynamic pages in a Nuxt + CMS bundle.
I send the URL to the server and if such a page exists I receive the data.
The data contains a list of components that I need to use, the number of components can be different.
I need to dynamically import these components and use them on the page.
I don't fully understand how I can properly import these components and use them.
I know that I can use the global registration of components, but in this case I am interested in dynamic imports.
Here is a demo that describes the approximate logic of my application.
https://codesandbox.io/s/dank-water-zvwmu?file=%2Fpages%2F_.vue
Here is a github issue that may be useful for you: https://github.com/nuxt/components/issues/227#issuecomment-902013353
I've used something like this before
<nuxt-dynamic :name="icon"></nuxt-dynamic>
to load dynamic SVG depending of the icon prop thanks to dynamic.
Since now, it is baked-in you should be able to do
<component :is="componentId" />
but it looks like it is costly in terms of performance.
This is of course based on Nuxt components and auto-importing them.
Also, if you want to import those from anywhere you wish, you can follow my answer here.
I used this solution. I get all the necessary data in the asyncData hook and then import the components in the created () hook
https://codesandbox.io/s/codesandbox-nuxt-uidc7?file=/pages/index.vue
asyncData({ route, redirect }) {
const dataFromServer = [
{
path: "/about",
componentName: 'myComponent'
},
];
const componentData = dataFromServer.find(
(data) => data.path === route.path
);
return { componentData };
},
data() {
return {
selectedRouteData: null,
componentData: {},
importedComponents: []
};
},
created() {
this.importComponent();
},
methods: {
async importComponent() {
const comp = await import(`~/folder/${this.componentData.componentName}.vue`);
this.importedComponents.push(comp.default);
}

Vue/Nuxt: How to define a global method accessible to all components?

I just want to be able to call
{{ globalThing(0) }}
in templates, without needing to define globalThing in each .vue file.
I've tried all manner of plugin configurations (or mixins? not sure if Nuxt uses that terminology.), all to no avail. It seems no matter what I do, globalThing and this.globalThing remain undefined.
In some cases, I can even debug in Chrome and see this this.globalThing is indeed defined... but the code crashes anyway, which I find very hard to explain.
Here is one of my many attempts, this time using a plugin:
nuxt.config.js:
plugins: [
{
src: '~/plugins/global.js',
mode: 'client'
},
],
global.js:
import Vue from 'vue';
Vue.prototype.globalFunction = arg => {
console.log('arg', arg);
return arg;
};
and in the template in the .vue file:
<div>gloabal test {{globalFunction('toto')}}</div>
and... the result:
TypeError
_vm.globalFunction is not a function
Here's a different idea, using Vuex store.
store/index.js:
export const actions = {
globalThing(p) {
return p + ' test';
}
};
.vue file template:
test result: {{test('fafa')}}
.vue file script:
import { mapActions } from 'vuex';
export default {
methods: {
...mapActions({
test: 'globalThing'
}),
}
};
aaaaaaaaand the result is.........
test result: [object Promise]
OK, so at least the method exists this time. I would much prefer not to be forced to do this "import mapActions" dance etc. in each component... but if that's really the only way, whatever.
However, all I get is a Promise, since this call is async. When it completes, the promise does indeed contain the returned value, but that is of no use here, since I need it to be returned from the method.
EDIT
On the client, "this" is undefined, except that..... it isn't! That is to say,
console.log('this', this);
says "undefined", but Chrome's debugger claims that, right after this console log, "this" is exactly what it is supposed to be (the component instance), and so is this.$store!
I'm adding a screenshot here as proof, since I don't even believe my own eyes.
https://nuxtjs.org/guide/plugins/
Nuxt explain this in Inject in $root & context section.
you must inject your global methods to Vue instance and context.
for example we have a hello.js file.
in plugins/hello.js:
export default (context, inject) => {
const hello = (msg) => console.log(`Hello ${msg}!`)
// Inject $hello(msg) in Vue, context and store.
inject('hello', hello)
// For Nuxt <= 2.12, also add 👇
context.$hello = hello
}
and then add this file in nuxt.config.js:
export default {
plugins: ['~/plugins/hello.js']
}
Use Nuxt's inject to get the method available everywhere
export default ({ app }, inject) => {
inject('myInjectedFunction', (string) => console.log('That was easy!', string))
}
Make sure you access that function as $myInjectedFunction (note $)
Make sure you added it in nuxt.config.js plugins section
If all else fails, wrap the function in an object and inject object so you'd have something like $myWrapper.myFunction() in your templates - we use objects injected from plugins all over the place and it works (e.g. in v-if in template, so pretty sure it would work from {{ }} too).
for example, our analytics.js plugin looks more less:
import Vue from 'vue';
const analytics = {
setAnalyticsUsersData(store) {...}
...
}
//this is to help Webstorm with autocomplete
Vue.prototype.$analytics = analytics;
export default ({app}, inject) => {
inject('analytics', analytics);
}
Which is then called as $analytics.setAnalyticsUsersData(...)
P.S. Just noticed something. You have your plugin in client mode. If you're running in universal, you have to make sure that this plugin (and the function) is not used anywhere during SSR. If it's in template, it's likely it actually is used during SSR and thus is undefined. Change your plugin to run in both modes as well.
This would be the approach with Vuex and Nuxt:
// store/index.js
export const state = () => ({
globalThing: ''
})
export const mutations = {
setGlobalThing (state, value) {
state.globalThing = value
}
}
// .vue file script
export default {
created() {
this.$store.commit('setGlobalThing', 'hello')
},
};
// .vue file template
{{ this.$store.state.globalThing }}

Page reload causes Vuex getter to return undefined

Using Vue.js (Vuetify for FE).
A page reload causes the getter in Vuex to fail with pulling required data from the store. The getter returns undefined. The code can be found on GitHub at: https://github.com/tineich/timmyskittys/tree/master/src
Please see the full details on this issue at timmyskittys.netlify.com/stage1. This page has complete info on the issue and instructions on how to view the issue.
Note, there is mention of www.timmyskittys.com in the issue description. This is the main site. timmyskittys.netlify.com is my test site. So, they are the same for all intents and purposes. But, my demo of this issue is at the Netlify site.
I read the complete issue in the website you mentioned. It's a generic case.
Say, for cat details page url: www.timmyskittys.com/stage2/:id.
Now in Per-Route Guard beforeEnter() you can set the cat-id in store. Then from your component call the api using the cat-id (read from getters)
I found the solution to my issue:
I had to move the call of the action which calls the mutation that loads the .json file (dbdata.json) into a computed() within App.vue. This was originally done in Stage1.vue.
Thanks all for responding.
I had the same issue and my "fix" if it can be called that was to make a timer, so to give the store time to get things right, like so:
<v-treeview
:items="items"
:load-children="setChildren"
/>
</template>
<script>
import { mapGetters } from 'vuex'
const pause = ms => new Promise(resolve => setTimeout(resolve, ms))
export default {
data () {
return {
children: []
}
},
computed: {
...mapGetters('app', ['services']),
items () {
return [{
id: 0,
name: 'Services',
children: this.children
}]
}
},
methods: {
async setChildren () {
await pause(1000)
this.children.push(...this.services)
}
}
}
</script>
Even though this is far from ideal, it works.

vue js trigger other component method

my files looks like this
./components/UserCreate.vue
./components/UserList.vue
./main.js
my vue instance in main.js
new Vue({
el: '#user-operations',
components: {
CreateUser,
UserList
}
});
index.html
<div id="user-operations">
<create-user></create-user>
<user-list></user-list>
</div
I want to trigger userList() method in UserList.vue when createUser() method in CreateUser.vue is triggered. Or how can i pass last_user property to UserList component from CreateUser.vue for append.
here is my create-user component [working]
https://jsfiddle.net/epp9y6vs/
here is my user-list component [working]
https://jsfiddle.net/ore3unws/
so i want the last user to be listed when createUser() is triggered
I recommend to create a service with all the methods operating user entities. It will separate your Components from the implementaton of the logic which is good because:
The Components doesn't have to know which calls they have to do to servers to retrieve data - it's better to use abstraction level
The Component will be lighter and easier for reuse
You will be able to use this logic (from the service) in several Components - exactly your problem
You have several ways to implement services:
Stateless service: then you should use mixins
Statefull service: use Vuex
Export service and import from a vue code
any javascript global object
I prefer (4). Here is an example how to do it:
In file /services/UsersService that will describe your service put all the relevant methods and expose them with export:
import axios from 'axios'
export default {
get() {
return axios.get('/api/posts)
}
}
Then in any Component that needs this methods import this service:
import UsersService from '../services/UsersService'
export default {
data() {
return {
items: []
}
},
created() {
this.fetchUsers()
},
methods: {
fetchUsers() {
return UsersService.get()
.then(response => {
this.items = response.data
})
}
}
}
Find even more about it in this question:
What's the equivalent of Angular Service in VueJS?
This solution is much better than using this.$parent.$refs.userList which suppose that this components will always stay "brothers" (will have the same parent).
You can trigger userList in CreateUser.vue by this code:
this.$parent.$refs.userList.userList()
and change your index.html:
<div id="user-operations">
<create-user></create-user>
<user-list :ref="userList"></user-list>
</div>
You can create last_user property in main.js then pass it to 2 components:
.
<div id="user-operations">
<create-user:lastUser="last_user"></create-user>
<user-list :lastUser="last_user"></user-list>
</div>

Vuejs + vue-router, pass data between views like http post

I'm try to pass data between Vuejs views with vue-router.
//View1.vue
route: {
data: function (transition) {
transition.next({
message: "this is it!!"
});
}
}
I call next wiew with a click action button with:
//View1.vue
methods:{
showResult: function(){
this.$router.go('/View2');
}
}
but the data are not filled in the next view:
//View2.vue
<template>
<p>Message: {{ message }}</p>
</template>
Does somebody knows what's wrong with my usage of vue-router? I don't think I need to pass through services for this, right?
Working examples on jsfiddle (or jsbin, etc) are welcome :D
If View2 is a child component you can pass it using props:
//View1.vue
<view2-component :passedData='message'></view2-component>
Alternatively, I believe if you set data on the $route object from View1, since that object is shared between all vue instances, I believe it will be available application-wide.
//View1.vue
this.$router.myProps.message = message
But arguably the better way to share data is use a POJO - plain old javascript object and bind it to both views. To do this you typically need a shared state object and you can if you wish use Vuex for this although it is a little more complicated than a POJO.
I know this has already been answered, but if someone is here looking for a way to pass data to a route from a router, I use Meta Data.
Not sure if this is what the questioner meant or not but I think it is?
I personally prefer this to props just because I am more used to using it.
It allows for data to be easily passed and received without having to modify children.
Anyway here is a snippit and link!
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Homepage',
meta: {
logo:{
"/imgs/Normal-Logo.png"
}
}
},
{
path: '/admin',
name: 'Admin',
meta: {
logo:{
"/imgs/Admin-Logo.png"
}
}
},
]
})
In any children who want to use vars:
<logo :src="this.$route.meta.logo"/>
Ref:
https://router.vuejs.org/guide/advanced/meta.html