In my vue app I have 2 methods, one method gets some data from my laravel backend and the second one needs to be able to grab it so that I can use it in that method.
What I'm struggling with is that the second method isn't grabbing the data.
Here is my code
<template>
<app-layout>
<div class="content-wrapper" style="margin-left: 0;">
<div class="content">
<div class="container">
<div class="row pt-5">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-lg-12">
Some data will show here
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</app-layout>
</template>
<script>
import AppLayout from '#/Layouts/AppLayout'
export default {
components: {
AppLayout,
},
data() {
return {
testData: ''
}
},
methods: {
firstMethod() {
axios.get('/api/get-data').then(response => {
this.testData = response.data;
});
},
secondMethod(){
console.log(this.testData);
}
},
mounted() {
this.firstMethod();
this.secondMethod();
}
}
</script>
your running both function in mount function so both run at same time and secondMethod() executed 1st at that time your this.testData is not set so you can use async and await to wait to finish firstMethod() then run secondMethod()
which will be like below code
<template>
<app-layout>
<div class="content-wrapper" style="margin-left: 0">
<div class="content">
<div class="container">
<div class="row pt-5">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-lg-12">
Some data will show here
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</app-layout>
</template>
<script>
import AppLayout from "#/Layouts/AppLayout";
export default {
components: {
AppLayout,
},
data() {
return {
testData: "",
};
},
methods: {
async firstMethod() {
const { data } = await axios.get("/api/get-data");
this.testData = data;
},
secondMethod() {
console.log(this.testData);
},
},
async mounted() {
await this.firstMethod();
this.secondMethod();
},
};
</script>
You can try calling firstMethod in created() hook instead of mounted. In my opinion you do not need a method for modifying incoming data. Use watch instead:
watch: {
// whenever question changes, this function will run
testData: function (newValue) {
// do what transformation you need here
}
}
Watch hooks run when value of variable changes, so it should run when it is assigned.
The problem that you dont see the console log is because even if you execute first the first method, it's actually executed after the second method because takes more time to be resolved.
Try the below please, inside first method i added after then to execute the second method which means that that the first method would be resolved, thus we will have the api response.
In case you continue seeing nothing from console log then there is an issue with the api endpoint.
mounted() {
this.firstMethod();
},
methods: {
firstMethod() {
axios.get('/api/get-data').then(response => {
this.testData = response.data;
this.secondMethod();
});
},
secondMethod(){
console.log(this.testData);
}
},
Related
good day;
i new in vue.js
i have simple problem when i using infinite scroll i make configuration as below but when page reloaded it must send request to data base to show data when page =1 this request not sent
i want help to get it work
this is my
this is service component
<template>
<div>
<!-- start covr-page --------------------- -->
<div class="covr-page">
<h2>خدمات لوجستية متكاملة </h2>
<div class="overlay"></div>
</div>
<!-- end covr-page --------------------- -->
<!-- start servic --------------------- -->
<div class="servic sections">
<div class="container">
<h3 class="start-title">
<img src="/images/start-title.png" alt="">
خدمات لوجستية متكاملة
</h3>
<div class="row">
<div v-for="service,key in list" class="col-lg-offset-3 col-lg-6 col-md-12 col-md-8 col-sm-offset-1 col-sm-10">
<a href="order-service.html">
<div class="email-signature">
<div class="signature-details">
<div class="signature-img">
<img :src="`upload/${service.icon}`" alt="">
</div>
</div>
<div class="contant-serv">
<h4>{{service.ar_name}}</h4>
<p>
{{service.ar_description}}
</p>
</div>
</div>
</a>
</div>
<infinite-loading #distance="100" #infinite="infiniteHandler"></infinite-loading>
</div>
</div>
</div>
</div>
</template>
this is my route
Route::get('/Services', 'ServicesController#Services');
this is my js code
<script>
export default {
name: "Services",
data: function () {
return {
list: [],
page:1
}
},
mounted(){
// this.infiniteHandler()
// axios.get('/Services')
// .then((response) =>{
// this.list=response.data
// }).catch((error) =>this.errors=error.response.data.errors );
},
methods: {
infiniteHandler($state) {
this.$http.get('/Services?page='+this.page)
.then(response => {
return response.json();
}).then(data => {
$.each(data.data, (key, value)=> {
this.list.push(value);
});
$state.loaded();
});
this.page = this.page + 1;
},
},
}
</script>
you have not declared vue-infinite-loading
import InfiniteLoading from 'vue-infinite-loading';
export default {
components: {
InfiniteLoading,
},
I have two components. Component 1:
<template>
<div>
<div class="form-group">
<label for="group">Category</label>
<select name="category" v-model="category" #change="setCategory(category)" class="form-control select-group" id="category">
<option value="1">Category 1</option>
<option value="2">Category 2</option>
</select>
</div>
<tags-multiselect :categoryId="category"></tags-multiselect>
</div>
</template>
<script>
export default {
data () {
return {
category: 1,
}
},
methods: {
setCategory(selected) {
this.category = selected;
},
},
}
</script>
Component 2:
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card card-default">
<div class="card-header">Example Component</div>
<div class="card-body">
I'm an example component.
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['categoryId'],
data () {
return {
category_ids: this.categoryId
}
},
created() {
axios.post('/tags', { category_id: this.categoryId })
.then((response) => {
//
})
.catch((err) => {
})
}
}
</script>
When I select option from first component, I not update category_id on second component with other id I get only 1 id. And when I send axios request with category_id I send always only first param 1. How I can resolve this? How I can refresh the second component with new selected data from select field?
props need to be kebab case in the template.
Try <tags-multiselect :category-id="category"></tags-multiselect>
Also, you don't need to redefine props in the data. Get rid of category_ids in component 2, it will just confuse things.
Then, Vue makes it very easy to extract your state from your components. Shared state (categoryId) and operations on shared state ( axios.post(...) ) would be much happier in global scope, according to me !
I am trying to make a carousel that shows a list of new tutors in a specific area from latest first. I am using laravel 5.6, vue.js and owl carousel.
Below I am using axios to retrieve from the database, and call owl-carousel
<script>
export default {
props: {
areaId: null,
},
data () {
return {
NewTutors: {}
}
},
methods: {
getNewTutor () {
var that = this;
axios.get( '/' + this.areaId + '/home/new').then((response) => {
that.NewTutorss = response.data;
})
.catch(error => {
console.log(error)
this.errored = true
});
}
},
mounted () {
this.getNewTutor();
}
}
$(document).ready(function() {
$('#NewHustles').owlCarousel();
});
</script>
and here and try and loop through each new tutor in a carousel.
<div class="owl-carousel owl-theme owl-loaded" id="NewTutors">
<div class="owl-stage-outer">
<div class="owl-stage">
<div class="owl-item" v-for="NewTutor in NewTutors>
<div class="card">
<div class="card-header">
{{NewTutor.name}}
</div>
<div class="card-body">
<div>
{{NewTutor.area.name}}
</div>
<div>
Image goes here
</div>
<div>
{{NewTutor.user.first_name}}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
I get all the cards, with the correct data passed through, but instead of a single row carousel, I get a big blob of cards that move as if there was only one item. I have tried Vue.nexttick, and playing around with a few other things, but nothing seems to work quite right.
Thank you for your help.
I want to add one component inside other when user clicks a button. but how can we render the component in the virtual dom.
I tried using v-html but its not working.
Whats the best way to solve this issue?
export default {
data(){
return{
elements : {
hotel : '<hotel-form></hotel-form>'
},
}
},
methods:{
addHotel(){
console.log('add');
}
}
}
<template>
<div class="container" style="margin-top:300px;">
<div class="row" id="mainform">
<div v-for="item in elements">
<div v-html="item"></div>
</div>
</div>
<button #click="addHotel()">add hotel</button>
</div>
</template>
I would bind an array (hotels) to a <hotel-form> component tag via v-for. This way, no hotel-form components will be initially rendered, and then you can push an object (with any data to want bound to the hotel-form component) to the hotels array and the DOM will automatically render a new corresponding hotel-form component.
Here's a simple example:
Vue.component('hotel-form', {
template: '#hotel-form',
props: { id: Number, name: String },
});
new Vue({
el: '#app',
data() {
return { hotels: [], count: 0 }
},
methods: {
addHotel() {
this.hotels.push({ name: 'foo', id: this.count++ })
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
<div id="mainform">
<hotel-form v-for="hotel in hotels" :key="hotel.id" v-bind="hotel">
</hotel-form>
</div>
<button #click="addHotel">add hotel</button>
</div>
<template id="hotel-form">
<div>
<h4>Hotel Form #{{ id }}</h4>
<div>{{ name }}</div>
</div>
</template>
I am new to Laravel and a complete noob to Vue. I searched many other Laravel/Vue posts but none seemed to be similar enough to get me to a solution. When attempting to load this component on my view I receive the following error
app.js:32654 [Vue warn]: Property or method "features" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
Please let me know what I am missing.
chrome.google.com/webstore/detail/vuejs-devtools/ shows that Vue is loaded
I would like to load data from an ajax call to my vue component. that can be updated on the fly by event handler
App.js
window.Vue = require('vue');
Vue.component('Example', require('./components/Example.vue'));
const app = new Vue({
el : '#app',
});
$(document).ready(function() {
$.ajaxSetup({
headers : {
'X-CSRF-TOKEN' : $('meta[name="csrf-token"]').attr('content')
}
});
})
Example.vue
<template>
<div class="container projects-container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Example Component</div>
<div class="panel-body">
<h1>I'm an example component!</h1>
<ul class="list-group">
<li class="list-group-item" v-for="feature in features">
{{ feature.properties.name }}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
}
</script>
bladefile
<head>
<meta name="csrf-token" content="INMA4kLlG32gfhf4Z3BBGIFxitrVCWzzqgqPfooEj">
// and yes Vue is loaded
</head>
<body>
<div id="app">
<example></example>
</div>
...
<script>
Vue.component('example',{
template: 'Example',
})
//returns the JSON listed below
someOtherObject.addListener('click', function(e) {
$.ajax({
url:json,
method:'GET',
success:function(msg){
app.data = JSON.parse(msg);
}
})
})
</script>
JSON
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"geometry":{
"type":"Point",
"coordinates":[
-117.155083,
33.569672
]
},
"properties":{
"heading":null,
"face":"South",
"status":"1",
"name":"MEADOWLARK ",
"type":"Single Family Home",
"client_id":"26",
"client_name":"Pulte Homes",
"city_name":"French Valley"
}
},
{
"type":"Feature",
"geometry":{
"type":"Point",
"coordinates":[
-117.151390,
33.543981
]
},
"properties":{
"heading":null,
"face":"South",
"status":"1",
"name":"Testing Project",
"type":"Single Family Home",
"client_id":"83",
"client_name":"Testing Account",
"city_name":"Temecula Valley"
}
},
{
"type":"Feature",
"geometry":{
"type":"Point",
"coordinates":[
-117.223720,
33.571522
]
},
"properties":{
"heading":null,
"face":"South",
"status":"1",
"name":"Oak Ridge",
"type":"Single Family Home",
"client_id":"98",
"client_name":"Woodside 05S LP",
"city_name":"Beaumont"
}
}
]
}
The features array must be declared either as a prop or part of the component data.
As a prop:
<template>
<div class="container projects-container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Example Component</div>
<div class="panel-body">
<h1>I'm an example component!</h1>
<ul class="list-group">
<li class="list-group-item" v-for="feature in features">
{{ feature.properties.name }}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
props: ['features']
}
</script>
As component data:
<template>
<div class="container projects-container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Example Component</div>
<div class="panel-body">
<h1>I'm an example component!</h1>
<ul class="list-group">
<li class="list-group-item" v-for="feature in features">
{{ feature.properties.name }}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
data: function() {
return {features: []}
}
}
</script>
If you use a prop, you'll need to bind the prop in the template. If you use component data, you'll need to update the success callback function in the AJAX request to correctly update the data of the component rather than the app as a whole.
Also, beware of the reactivity caveats for loading new data, as outlined in the docs.
EDIT: Full example solution using component data
Here's a working example using a simplified version of your example component. Note that to do this I used the ref attribute so that the component could be addressed directly. Using refs is described in the docs as an "escape hatch" that should only be used when strictly necessary. A better pattern might be an external store, such as Vuex.
Vue.component( "example", {
template: '<div><h1>Example Component!</h1><ul v-if="features.length"><li v-for="feature in features">{{ feature.name }}</li></ul></div>',
data: function() {
return { features : [] }
}
});
var app = new Vue( { el: '#app' });
//A function to represent the AJAX callback
var doMockAjax = function() {
var mockData = [{name: 'One'},{name: 'Two'},{name: 'Three'}];
app.$refs.example.features = mockData;
}
document.getElementById('load-data').addEventListener('click', function(e) {
//This simulates the ajax callback by populating the array asynchronously
setTimeout(doMockAjax,1000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
<example ref="example"></example>
</div>
<button id="load-data">Load</button>