I'm trying to get Vue components working in Laravel 5.3 and I want to pass data from my blade template to a Vue component.
But I'm getting an error and none of the answers I've found so far have worked.
I'm using the example component that comes with the fresh install. In my blade template I have:
<example :testinfo="someinfo"></example>
In my Example.vue I have:
<template>
<div class="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">
{{testinfo}} I'm an example component!
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['testinfo'],
mounted() {
console.log('Component ready.')
}
}
</script>
The Vue component does load, but it does not display the testinfo, and it generates this error message:
Property or method "someinfo" is not defined on the instance but
referenced during render. Make sure to declare reactive data
properties in the data option. (found in root instance)
referenced to your error ->
Property or method "someinfo" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. (found in root instance)
it means that someinfo model is not declared from your vue parent. it should be wrapped in data { someinfo:null } and from there supply him data and pass it in your component example.
regarding passing with data from vue blade. you should called ajax from your vue method like
Vue new(){
data : { someinfo : null },
ready :function() / mounted() vue2
{
this.getSomeInfo();
}
methods : {
getSomeInfo : function(){
var self = this;
your ajax request here then
self .someinfo = (your ajax.response)
}
}
}
you need an sperate ajax call from controller to achieve to get your information from controller.
after ajax call success then time to put the response to your vue model then it will automatically pass to your components re actively because of two way binding.
The answer from Tony Fale wasn't exactly what I was looking for but it did give me a clue that helped me think of the answer.
In this code:
<example :testinfo="someinfo"></example>
I thought "someinfo" would just be treated as a string but Vue treats it as a JavaScript variable. Since someinfo isn't defined anywhere, it causes an error.
If instead I do:
<example :testinfo="{somekey: 'someinfo'}"></example>
and change Example.vue to:
<template>
<div class="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">
{{testinfo.somekey}} I'm an example component!
</div>
</div>
</div>
</div>
</div>
</template>
It works as expected.
Related
I have a modal component which uses Alpine, which I made into a Blade component.
// Modal blade component
<div x-data="{ open = false }">
<div x-show="open"></div>
</div>
I want to share the open state with a Livewire component, but I don't know how to pass the #entangle directive through the component:
// Livewire component
<x-modal>
</x-modal>
I tried this:
// Modal Blade component
<div {{ $attributes }}>
<div x-show="open"></div>
</div>
// Livewire component
<div x-data="{ open = #entangle('livewire-state')}">
<div x-show="open"></div>
</div>
But the entangle directive just get parsed into string.
Your x-data object isn't properly syntaxed. You are using a = instead of a :. You should be seeing a console error also, if you happened to have the console open. Use the following syntax:
<div x-data="{ open: #entangle('livewire-state')}">
Read more on #entangle in the docs.
In Vue3, inline-templates were depreciated and now slots are used. Is it possible to have 2-way binding of variables for Vuejs components written in blade templates?
I want to have 2-way binding for Vue components that's written inline with blade templates. Although I know I can pass data like <example-component name="Hello World"> It is a ton of work to add props everywhere.
Vue recommends using slots as a inline-template replacement since it got removed in v3, however, that documentation makes no sense. I've got the components displayed using the code below. It's a dead simple text field + paragraph to display the name.
home.blade.php (Removed unnecessary HTML for brevity)
<div>
<h1>Dashboard</h1>
<example-component>
<div class="container">
<input v-model="name" placeholder="Change Name"/>
<p> Name is #{{ name }} </p>
</div>
</example-component>
</div>
example-component.vue
<template>
<div>
<slot></slot>
</div>
</template>
<script>
export default {
data() {
return {
name: 'hi',
}
}
}
</script>
Unfortunately, this does not work, the name doesn't start as 'hi' and doesn't update when changing the textfield. When I try something like <slot :name=name></slot>. Which I believe would pass the name into the slots section, the component gets rendered for a second before disappearing.
Is having 2-way binding with vue variables in blade templates even possible? Any help is appreciated.
Vue: 3.0.5
Laravel: 8.29.0
Is there a reason you're storing the data in the child component? The reactivity design works by passing props down and emitting events up, even though (unfortunately) the reactivity is not maintained when passing a variable up to the parent component. Seems a little counter intuitive, but I might be missing something in what you're trying to create.
It will, however, work if you put the data into the app instead of the component.
// app
const app = Vue.createApp({
data() {
return {
name: 'hi',
}
}
})
// component
app.component('example-component', {
template: `
<div>
<slot></slot>
</div>`,
})
app.mount("#app");
<script src="https://unpkg.com/vue#3.0.5/dist/vue.global.prod.js"></script>
<div id="app">
<h1>Dashboard</h1>
<example-component>
<div class="container">
<input v-model="name" placeholder="Change Name"/>
<p> Name is #{{ name }} </p>
</div>
</example-component>
</div>
<!--
I am trying to build a very simple, tinder-like swiping application using Laravel Spark and vue2-touch-events. I assume I am doing something extraordinarily dumb, so I appreciate your insight.
I get this warning in my Vue inspector:
[Vue warn]: Property or method "swipeHandler" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
Here is my simple version of all of the relevant code. I changed the v-touch:swipe to just longtap for testing.
/resources/js/app.js:
require('spark-bootstrap');
require('./components/bootstrap');
require('vue2-touch-events');
Vue.component('swipeHandler', './components/swipehandler.vue');
var app = new Vue({
mixins: [require('spark')],
components: {
vue2touchevents,
swipeHandler
},
});
swipe.blade.php:
#extends('spark::layouts.app')
#section('content')
<home :user="user" inline-template>
<div class="container">
<div class="row justify-content-center flex-column-reverse flex-md-row">
<div class="col-md-8">
<div class="card text-center">
<div class="card-header">
<div><i v-touch:longtap="swipeHandler">Swipe Here</i></div>
</div>
</div>
</div>
</div>
</div>
</home>
#endsection
/resources/js/components/swipehandler.vue:
<script>
export default {
methods: {
swipeHandler () {
alert("yay!");
console.log("yay!");
}
}
}
</script>
My Best guess is that you may want to try and add a template to your /resources/js/components/swipehandler.vue component:
<template>
<div>Yay</div>
</template>
<script>
export default {
methods: {
swipeHandler () {
alert("yay!");
console.log("yay!");
}
}
}
</script>
I'm not too familiar with how vue2-touch-events works, so I would need to understand that a bit more to give you a better answer.
Best of luck.
Firstly I'm Laravel Spark and have successfully integrated into the mix installation so my js is being deployed into app.js already
I am getting errors when I setup a new component for a project;
blade file
#extends('spark::layouts.app')
#section('content')
<div class="container">
<!-- Application Dashboard -->
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Sprints</div>
<div class="panel-body">
<os-sprints></os-sprints>
<input type="text" v-model="newSprint">
<button #click="addSprint">add</button>
</div>
</div>
</div>
</div>
</div>
<template id="my-sprints">
<ul class="list-group">
<li class="list-group-item" v-for="sprint in sprintlist">
<a :href="'/sprints/' + sprint.id">#{{ sprint.title }} #{{ sprint.id }} </a>
</li>
</ul>
</template>
#endsection
and my js
Vue.component('os-sprints', {
template: '#my-sprints',
data() {
return {
sprintlist: [],
newSprint: ''
};
},
created() {
this.getSprints();
},
methods: {
getSprints() {
axios.get ('/api/team/sprints')
.then(response => {
this.sprintlist = response.data;
});
},
addSprint() {
alert("hit");
// this.sprintlist.push(this.newSprintname);
// this.newSprintname = '';
},
}
});
The errors I'm getting in console;
app.js:42229 [Vue warn]: Property or method "newSprint" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
(found in <Root>)
warn # app.js:42229
app.js:42229 [Vue warn]: Property or method "addSprint" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
(found in <Root>)
warn # app.js:42229
app.js:42229 [Vue warn]: Property or method "sprintlist" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
(found in <Root>)
warn # app.js:42229
app.js:42229 [Vue warn]: Invalid handler for event "click": got undefined
I'm getting a sprintlist data fine but even without the text field and button I'm getting errors and my button method never hits.
Any feedback would be greatly appreciated
Chris!
This type of warning is usually caused by a variable not being defined yet. (I know, not very helpful). What I mean:
You passing a variable from one component A to another component B
While a variable is still being passed (have not reached the desired component B), component B is already being mounted
since a component B is already mounted, it is trying to use a variable that hasn't reached yet (ta da -> a warning)
Then a variable reached, Vuejs reacted and updated the view accordingly
This warning can be avoided by adding a v-if to an element or a wrapper
That's because you reference your data object properties and methods of a child component in parent component.
Move
<input type="text" v-model="newSprint">
<button #click="addSprint">add</button>
into your child component's template and you should be fine.
Ok I worked it out, I had tried to do what MatWaligora had suggested previously but the issue was I didn't realise I needed a single "parent" within the template. After I changed it to the below I got the functionality working. I'm still getting Vue warning messages as above but the page works.
<template id="my-sprints">
<div>
<ul class="list-group">
<li class="list-group-item" v-for="sprint in sprintlist">
<a :href="'/sprints/' + sprint.id">#{{ sprint.title }} #{{ sprint.id }} </a>
</li>
</ul>
<input type="text" id="sprinttext" v-model="newSprint">
<button #click="addSprint">add</button>
</div>
</template>
For me it was an extra closing tag in the loop.
<div v-for="(item, index) in items" :key="index">
<a :href="item.url">{{ item.name }} </a>
</div> // <- the issue
</div>
Double check all tags if other answers didn't help you.
I seem to be misunderstanding how to pass data to a Vue.js component with an ajax call.
My understanding of how this should work:
I need to create an empty object called campaigns in the data section of my component.
Then call method "fetchCampaigns" on page ready to replace the data object.
fetchCampaign method completes an AJAX call and inside of the success callback use this.$set('campaigns', campaigns) to replace the empty campaign object with the newly returned campaign object
Use v-for on the template to iterate through the campaign object and access values with #{{campaign.type}}
My html (I am use vue router, vue resource and laravel blade) :
<router-view></router-view>
<template id="campaignBlock" v-for="campaign in campaigns">
<div class="row">
<div class="block">
<div class="block-title">
<h2>Type: <em>#{{campaign.id}}</em></h2>
</div>
<div class="row"><!-- Grid Content -->
<div class="hidden-sm hidden-xs col-md-4 col-lg-4">
<h2 class="sub-header">#{{campaign.title}}</h2>
</div>
</div>
</div><!-- END Grid Content -->
</template>
Vue component
Vue.component('app-page', {
template: '#campaignBlock',
data: function() {
return{
campaigns: []
}
},
ready: function () {
this.fetchCampaigns();
},
methods: {
fetchCampaigns: function () {
var campaigns = [];
this.$http.get('/retention/getCampaigns')
.success(function (campaigns) {
this.$set('campaigns', campaigns);
})
.error(function (err) {
campaigns.log(err);
});
},
}
})
This is the result of my ajax call from console:
{"campaigns":[{"id":1,"user_id":2,"target_id":1,"name":"Test Campaign","description":"This is a test Campaign","target":"Onboarding","created_at":"-0001-11-30 00:00:00","updated_at":"-0001-11-30 00:00:00","deleted_at":null}]}
I'm not sure why I can't get my vue component to recognize the new data. Anyone see what I'm missing? TIA
Turns out that v-for="campaign in campaigns" should not go on the template tag, but inside of it.
So this:
<template id="campaignBlock" v-for="campaign in campaigns">
<div class="row">
Should be changed to this:
<template id="campaignBlock">
<div class="row" v-for="campaign in campaigns">