I have a page where I want to display a message if a user comes from a certain URL:
If arriving from this URL:
http://www.testapp.com?_a=lookingforthis&token=5b6b7f/account/about
<template>Show this message</template>
If from here:
http://www.testapp.com/account/about
<template>Dont show this message</template>
Would I need to do this in mounted() or method()?
Id this the correct way to trigger this?
this.$route.query?.lookingforthis
Something like this should work well
<template>
<div>
{{ showOrNotTheMessage }}
</div>
</template>
<script>
export default {
computed: {
showOrNotTheMessage() {
return this.$route.query?.lookingforthis
? 'Show this message'
: 'Dont show this message'
},
},
}
</script>
Being triggered on an URL like http://localhost:3000/about?lookingforthis=TEST.
As shown if using the Vue devtools
PS: if TEST is missing, it's falsy as expected.
Related
I have a tricky communication issue between a router-link in my parent Vue component and a child component.
I would like to clear an input field on the child component, which is the main Index for my app. This component loads by default.
The parent App component contains the main navigation which contains a router-link routed back to the index like so:
<router-link :to="{ name: 'Index', query: { search: '' }}" class="nav-link">
Index
</router-link>
The Index component contains a search input to filter the index items list. The search value is tracked by the component's data.
data() {
return {
items: [],
tags: [],
search:'',
}
The issue is I cannot seem to clear the search input when the router-link for the Index is clicked. I assume because the Index is already mounted clicking the link cannot trigger any function in the component.
I have tried using $emit by wrapping the link text in <span #click="clearSearch()">, putting the $emit in the clearSearch function and picking it up in the Index, but this apparently doesn't work from parent to child??
As you can see in the router-link above I have also tried passing as query like query: { search: '' } and adding the following to the main.js route configuration.
props(route) {
return { search: route.query.search }
}
This sends the empty string in URL but I still cannot pick it up in the Index component to clear the search input, again I think because it is already mounted.
This seems like it should be an easy thing to do, but I am a bit stumped on it and don't know what else to try. I am still learning Vue so there might be something obvious I am missing. If anyone can help me out on how to achieve this I would much appreciate it. Thanks in advance.
An easy hack would be to use router.push() in a method instead of <router-link> and to make search a prop and clear it from the parent.
This way you can store search in the parent data and clear it on click.
// Parent component
<template>
<div #click="navigate" class="nav-link">
Index
</div>
...
<Index :search="search" />
</template>
<script>
export default {
data() {
return {
search: ''
}
},
methods: {
navigate() {
this.$router.push({ name: 'Index' });
this.search = '';
}
}
}
</script>
// Child component
<template>
{{ search }}
</template>
<script>
export default {
props: {
search: {
type: String,
default: '',
}
}
}
</script>
I have a Nuxt project with Buefy components. There is a form with some field component which should react on error according the message parameter for this component. But does not. I can see the correct value in debuger but component does not show the message. :message property should work like the in first email example from documentation
The code looks like:
<template #company>
<h2 class="title">{{ $t('general.login.create_company') }}</h2>
<b-field
:type="loginErrors.company_name ? 'is-danger' : ''"
:message="loginErrors.company_name ? loginErrors.company_name : ''"
>
<b-input
v-model="companyName"
name="company_name"
type="text"
autocomplete="off"
:placeholder="$t('general.login.create_company')"
></b-input>
</b-field>
<div class="buttons is-centered">
<b-button type="is-primary is-light" #click="createCompany">Save</b-button>
</div>
</template>
...
data() {
return {
...
loginErrors: {},
error: 'aaaaaa',
};
},
...
async createCompany() {
const result = await this.$api.users.createCompany({company_name: this.companyName});
if( result.error ) {
this.loginErrors.company_name = result.error; // This does not work although the variable has correct value set
this.error = result.error; // This works fine
return false;
}
},
I use this pattern in other components and it works. I dont understand it. thaks for any help.
change detection of data objects in Vue is shallow (top level only)
In vue.js, Dynamically added property to an object is not reactive. Instead we can assign a whole object so that change detection happen.
For a better understanding please go through this official documentation of Vue.
Demo :
new Vue({
el: '#app',
data() {
return {
loginErrors: {}
}
},
mounted() {
this.loginErrors = {
company_name: 'some value'
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p>{{ loginErrors.company_name ? 'is-danger' : 'no-danger' }}</p>
</div>
I don't think Vue components react to object property changed in a direct way, you could try this.$set(this.loginErrors, 'company_name', result.error); instead of this.loginErrors.company_name = result.error;
FYI: https://v2.vuejs.org/v2/guide/reactivity.html?redirect=true#Change-Detection-Caveats
The solution in this case was to update Buefy version from 0.4.11 to 0.4.21. This fix the issue. Another thing is that is causes new issue with :type in combination with grouped param.
Axios and Vuejs
I am receiving data from the api,
but some items are null,
and I get a message on the console,
how can I deal with these errors
I tried to make a filter but it didn't work.
link: App
It would help if you could post some of your code from your Vue component, but there are many ways to deal with this. In general, you need to check for the value before displaying. Below are a couple of ways you could do this with Vue.
One way is using v-if. If the network is not null, show the network
<div v-if="show.network">{{ show.network }}</div>
You could also use a v-else directive to display something else
<div v-if="show.network">{{ show.network }}</div>
<div v-else>network unavailable</div>
Another way is to use a computed property.
<template>
<div>
<div>{{ network }}</div>
</div>
</template>
<script>
export default {
data: function() {
return {
show: {
network: null
}
}
},
computed: {
network() {
return ( this.show.network ) ? this.show.network : "not available";
}
}
};
</script>
The list goes on... As the developer, you will need to check the value to determine if it can be shown before displaying it.
From your template, you can use this code:
<p><span>Network: </span>{{ result.show?.network?.name || '' }}</p>
All browsers dont support ? so below will always works:
<p><span>Network: </span>{{ result.show && result.show.network && result.show.network.name }}</p>
i'm new here so hope everything is ok.
I'm building a search filter with ajax, using a proper controller for filtering my data and send the result to ajax.
At this point i would like to "append" my vue component and bind the data result.
Searching on google this is the "wrong" way, because js and vue.js use different methods to render to DOM.(right?)
I found that the correct way, could be send the results data from ajax (in some way) to my vue component.
How can i do this, in laravel?
app.js :
Vue.component('template', require('./components/template.vue').default;
const app = new Vue({
el:'#mytemplate',
});
template.vue :
<template>
<div>{{ title }}</div>
</template>
<script>
export default{
props:['title'],
}
</script>
my ajax:
success: function(data){
for(var i = 0; i < 10;i++){
name = data[i];
//what i would is
// $('#template').empty();
//$('#template').append('<template title="'+ name +'"></template>');
}
}
Thank you very much in advance at all!!
In your Vue template, perform an ajax request on the mounted hook to fetch data and bind it to the title data object instead of a prop
You can have the Vue component always present in your Blade view file and rendered or shown conditionally when the data loads
Something like this should work
template.vue
<template>
<div v-show="shown">
<div v-for="title in titles" :key="title">
{{ title }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
shown: false,
titles: [],
}
},
mounted() {
axios.get('/route').then(response => {
this.titles = response.data;
this.shown = true;
});
}
}
</script>
I would like to call a function with a value when a user starts typing in an input box. I have tried two approaches.
The first approach is trying to use two-way binding to a model. However, after following the documentation I get an error.
Here is the example from the official docs:
<div id="app-6">
<p>{{ message }}</p>
<input v-model="message">
</div>
var app6 = new Vue({
el: '#app-6',
data: {
message: 'Hello Vue!'
}
})
And here's my example:
<template lang="html">
<input
type="text"
v-model="handle"
/>
</template>
<script>
export default {
data: {
handle: 'model',
}
};
</script>
I am writing this as part of an application so I chose not to recreate the Vue instance and I declared that elsewhere. However, I get this error:
Property or method "handle" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
A second approach I've tried is this calling a function directly from the view via an event handler. I'm coming from React so this is my preferable approach. However, the function has undefined as an input value meaning it's not picking up the value of the input.
<template lang="html">
<input
type="text"
v-on:keyup="handleInput()"
/>
</template>
<script>
export default {
methods: {
handleInput(input) {
// input -> undefined
},
},
};
</script>
I really can't see why neither of these works. Wouldn't the expected behavior of an input listener would be to pass the value?
Where am I going wrong?
It seems like you might have to do something like this: How to fire an event when v-model changes ? (vue js). What I don't understand is why you have to manually attach a watcher when you have assigned a v-model? Isn't that what a v-model is supposed to do?
What finally worked was this:
<template lang="html">
<input
type="text"
v-model="searchTerm"
#keyup.enter="handleInput"
/>
</template>
<script>
export default {
data() {
return { searchTerm: '' }
},
methods: {
handleInput(event) {/* handle input */},
},
};
</script>
Shouldn't data be a function on your first example? I think this is how it works for vue components.
<script>
export default {
data: function () {
return { handle: 'model' }
}
};
</script>
I think this was explained somewhere on vuecasts.com, but I might be wrong. :)