Console Errors: [Vue warn]: Property or method is not defined on the instance but referenced during render - laravel

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.

Related

Alpinejs property bound to x-show not defined

I'm building a form in Laravel's Blade syntax, and using AlpineJs for some interactivity stuff like showing and hiding content.
My code is here:
<div class="flex items-center" x-data="destinationBuilder">
<x-label required="true" class="mr-5">Destination:</x-label>
<x-basic-input #change="handleDestinationChange" ::value="destination" placeholder="https://google.com"/>
<x-buttons.primary class="ml-5" #check="validateDestination">Check</x-buttons.primary>
</div>
<div class="mt-4">
<button type="button"
class="p-5 w-full text-sm grid grid-cols-[min-content_min-content_auto_min-content] items-center gap-x-3 font-light text-gray-400 hover:bg-gray-300 rounded-full"
#click.camel="toggleAdvancedOptions">
<i class="lni lni-cog"></i>
<span class="whitespace-nowrap">Advanced options</span>
<div class="h-px w-full bg-gray-400"></div>
<i class="lni lni-chevron-down"></i>
</button>
<div x-show="advanced" x-transition x-cloak>
{{-- <x-links.get-parameter-form/>--}}
</div>
</div>
#push('footer-scripts')
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('destinationBuilder', () => ({
destination: '',
advanced: false,
handleDestinationChange() {
if (this.validateDestination()) {
// emit constructed destination up
}
},
validateDestination() {
// check url is in a legit form (with https)
// basic is just url input
// advanced dropdown with get parameters, fragment, http protocol and port
},
toggleAdvancedOptions() {
this.advanced = !this.advanced;
}
}));
})
</script>
#endpush
I'm using a property named advanced to bind to x-show for another component.
When I look in my browser I get the following message: app.js:434 Uncaught ReferenceError: advanced is not defined
I'm not sure if this is due to a weird collision with blade or if I'm missing something fundamental with Alpinejs. I tried renaming the variable to showAdvanced but that didn't work either. I would expect advanced to be recognised as a property and bind to x-show as expected. What am I doing wrong here?
You have the following HTML structure:
<div x-data="destinationBuilder">
...
</div>
<div>
<div x-show="advanced">
...
</div>
</div>
As you see, the second div is not a child element of the first one where the x-data is defined, so it's outside of the scope of destinationBuilder component. Just create a common div (or similar) element that embeds both divs and apply the component x-data there, so each div will have access to the component's scope.

How to pass livewire entanglement into Alpine component

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.

Laravel 8 Livewire component Undefined variable: header

I have created a Livewire component in Jetstream and I have set it as a full-page component in the web.php route page as follows:
use App\Http\Livewire\PostComponent;
...
Route::get('posts/',PostComponent::class)->name('posts');
The post-component.blade.php file has originally the following code:
<div>
<h1>If you look to others for fulfillment, you will never truly be fulfilled.</h1>
</div>
If I hit the URL .../posts I get the following error:
Undefined variable: header (View:
/home/vagrant/laravelapp/resources/views/layouts/app.blade.php)
So I have tried adding the slot in the post-component.blade.php file:
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div>
<h1>If you look to others for fulfillment, you will never truly be fulfilled.</h1>
</div>
</x-app-layout>
Nevertheless, I get that same error.
What am I missing? How do I fix this?
I hope this is a Jetstream project. By default, livewire will use the app.blade.php as the layout. And the component will get rendered in the slot of the app.blade.php.
But since it's a Jetstream project, it has a slot for the header in the layout file.
<header class="bg-white shadow">
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
{{ $header }}
</div>
</header>
So to resolve this error, there are two approaches.
give the header as the variable for the layout as below in your PostComponent.php
public function render()
{
return view('livewire.post-component')
->layout('layouts.app', ['header' => 'Post Compoent Page']);
}
Create your own layout and only have a slot. (imagine mylayout.blade.php)
<head>
#livewireStyles
</head>
<body>
{{ $slot }}
#livewireScripts
</body>
and use that layout when rendering the livewire component
public function render()
{
return view('livewire.post-component')->layout('layouts.mylayout');
}
There is a github issue regarding this topic (a closed one). But keep an eye on it. since Jetstream is in it's early stages.

Can't pass data from blade to vue (Laravel 5.3)

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.

vue.js 2.0 load component dynamically in laravel 5.3

Is it possible to load a component dynamically when clicking a list item in vuejs 2.0 and laravel 5.3? I have a standard Laravel app but on one section of the site (shows reports) I want to turn this page into a single page application using vuejs. I load the default report in using a vue component and all works well, like so:
<div class="col-md-3 col-sm-6">
<div class="card-box">
<h2>Reports</h2><br>
<ul>
<li>Daily</li>
<li>Weekly</li>
<li>Season</li>
<li>Label</li>
<li></li>
</ul>
</div>
</div>
<div class="col-md-9 col-sm-6">
<div class="card-box main">
<reports-homepage></reports-homepage>
</div>
</div>
What I'm trying to achieve is when one of the li items is clicked the <reports-homepage></reports-homepage> is changed dynamically according to which li is pressed. So it could become <reports-daily></reports-daily> for example.
I've tried putting a #click on the li component and catching that in a script below in the blade section but that gives me the following error:
[Vue warn]: Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as <script>.
As pointed in the official documentation you can use dynamic components. In your case it could look something like this:
HTML
<div id="app">
<div class="col-md-3 col-sm-6">
<div class="card-box">
<h2>Reports</h2><br>
<ul>
<li #click="setComponent('daily')">Daily</li>
<li #click="setComponent('weekly')">Weekly</li>
<li #click="setComponent('season')">Season</li>
<li #click="setComponent('label')">Label</li>
</ul>
</div>
</div>
<div class="col-md-9 col-sm-6">
<div class="card-box main">
<component v-bind:is="currentComponent"></component>
</div>
</div>
</div>
JS
var vm = new Vue({
el: '#app',
data: {
currentComponent: 'daily'
},
components: {
'daily': { /* component object */ },
'weekly': { /* component object */ },
'season': { /* component object */ },
'label': { /* component object */ }
},
methods: {
setComponent: function (component) {
this.currentComponent = component;
}
}
})
And that should do what you are trying to achieve. Let me know if it helped!

Resources