Cannot use v-for on stateful component root element because it renders multiple elements? - laravel

app.js
var Users = {
template: `
<tr v-for="list in UsersData">
<th>{{ list.idx }}</th>
<td>{{ list.id }}</td>
</tr>
`,
data: function () {
return {
UsersData //get data from query
}
}
}
var mainview = new Vue({
el: "#mainview",
components: {
'users': Users
},
method: {}
})
layout.blade.php
<body>
<div class="container">
<aside>...</aside>
<main id="mainview">
#section('content')
#show
</mainview>
</div>
</body>
index.blade.php
#extends('layout')
#section('content')
<table>
<thead>
<tr>
<th>IDX</th>
<th>ID</th>
</tr>
</thead>
<tbody>
<users></users>
</tbody>
</table>
#endsection
ERROR LOG from chrome console
[Vue warn]: Cannot use v-for on stateful component root element because it renders multiple elements:
<tr v-for="list in UsersData">
<th>{{ list.idx }}</th>
<td>{{ list.id }}</td>
</tr>
vue.js:525 [Vue warn]: Multiple root nodes returned from render function. Render function should return a single root node.
(found in component )
How should I fix code?

Your template has to have one root element. It's just one rule you cannot break. Since you're making a table, it would make sense to make tbody the root element.
var Users = {
template: `
<tbody>
<tr v-for="list in UsersData">
<th>{{ list.idx }}</th>
<td>{{ list.id }}</td>
</tr>
</tbody>
`,
data: function () {
return {
UsersData //get data from query
}
}
}
index.blade.php
#extends('layout')
#section('content')
<table>
<thead>
<tr>
<th>IDX</th>
<th>ID</th>
</tr>
</thead>
<users></users>
</table>
#endsection

For the lazy: Vue interprets the root element having a v-for loop on it as producing multiple root level elements (a nono in modern JS frameworks).
Just wrap your template in a superfluous blank <div>. 👌

I struggled with this, until I realized you can just add a section tag over everything in template and then this error goes away.
Example
//gives error
<template>
<div classname="allFutures" v-for="(items, index) in arr">
<Future title="Shee" />
</div>
</template>
// do this instead
<template>
<section id="main" class="main-alt">
<div classname="allFutures" v-for="(items, index) in arr">
<Future title="Shee" />
</div>
</section>
</template>

Related

data-checkbox data-click-to-select not working reactjs

This code performs a render of a bootstrap table. In this table there are 2 columns with data and a total of 4 rows. I wish to have a checkbox at the side before the first column of data to select the entire row of data. I have tried using "data-click-to-select" and "data-checkbox", but no check box appears. What should I do to enable the selection of data by row?
Not sure if its because I'm not importing any react-bootstrap modules.
import axios from 'axios';
import React, { Component } from 'react';
import { table } from 'react-bootstrap'; // this is reflected as an unused variable
This is the example I tried to follow to get the checkbox: https://live.bootstrap-table.com/example/methods/get-selections.html
render() {
const obj = (this.state.message);
const datamapping = Object.entries(this.state.message);
return (
<div>
<div className="viewall">
<table class="table table-hover" data-click-to-select="true">
<thead>
<th data-checkbox="true"></th>
<th scope="col">key1</th>
<th scope="col">key2</th>
</thead>
<tbody>
{obj.Items?.map((data, key) => {
return (
<tr key={key}>
<td></td>
<td>{data.key1}</td>
<td>{data.key2}</td>
</tr>
)
})}
</tbody>
</table>
</div>
</div>
);
}
Found a workaround solution that does not hinge on data-checkbox or data-click-to-select - by clicking on a button that is present on each row and sending the key (array number) together with the data over.
handleClick(obj, i) {
//this.props.history.push("/signIn.js");
console.log(obj.Items[i]);
}
render() {
const obj = (this.state.message);
const datamapping = Object.entries(this.state.message);
return (
<div>
<div className="viewall">
<table class="table table-hover">
<thead>
<th data-checkbox="true"></th>
<th scope="col">key1</th>
<th scope="col">key2</th>
</thead>
<tbody>
{obj.Items?.map((data, key) => {
return (
<tr key={key}>
<td>
<button type="button" class="btn btn-primary" onClick={ () => this.handleClick(obj, key)}>
Sign In
</button>
</td>
<td>{data.key1}</td>
<td>{data.key2}</td>
</tr>
)
})}
</tbody>
</table>
</div>
</div>
);
}

How to fill the second html table by clicking a button from the first table when both of them are on the same page in Laravel?

I am using Laravel with mySql. I have two table in blade view, one in main div which contains a button to open the second which is in aside div and fill it with data retrieved from the controller. Please find below my code:
my routes
// showing list of orders
Route::get('orders/show/all', 'OrderController#showOrders')->name('orders.show.all');
// showing order details
Route::get('orders/details/{id}', 'OrderController#showOrderDetails')->name('orders.details');
my controller (OrderController), copied only two functions which have to do with this
public function showOrders(){
$orders = Order::orderBy('total_amount', 'desc')
->where('user_id','=', Auth::user()->id)
->get();
return view('orders.undo_sales', compact('orders'));
}
public function showOrderDetails($id){
$ordered_item = Order::findOrFail($id);
return redirect('orders/show/all', compact('ordered_item'));
}
}
my blade.php file
<main class="col-sm-8">
#include('partials.messages')
<div class="card">
<div class="card-header">List of all sales</div>
<div class="card-body">
<table class="table ">
<thead>
<tr>
<th>Order #</th>
<th>Order Date</th>
<th>Total Amount</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
#foreach ($orders as $order)
<tr>
<td>{{ $order->id }}</td>
<td>{{ $order->created_at }}</td>
<td>{{ number_format($order->total_amount) }}</td>
<td>
Order details
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
</main>
<aside class="col-sm-4" id="aside">
<div class="card">
<div class="card-header">Order Details</div>
<div class="card-body">
<table class="table ">
<thead>
<tr>
<th>Item Name</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
#foreach ($ordered_item->items as $value)
<tr>
<td>{{ $value->item_name }}</td>
<td>{{ number_format($value->pivot->quantity_on_order) }}</td>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
</aside>
</div>
<script>
let showDetails = document.querySelector('.show-details')
let aside = document.querySelector('#aside')
aside.style.display = 'none'
function showDiv(){
aside.style.display = 'block'
}
</script>
There is no problem with filling the main (first) table with data from the controller. The problem is getting the object returned by the function showOrderDetails($id) to the same view but on a different table and display those records. I tried to dd() the data in the controller on this method and I could see the item_name and the respective quantity. Which proved that there is no problem with this code in blade file:
#foreach ($ordered_item->items as $value)
<tr>
<td>{{ $value->item_name }}</td>
<td>{{ number_format($value->pivot->quantity_on_order) }}</td>
</tr>
#endforeach
But when I sent to the view I got the error in my view file:
Undefined variable: ordered_item
Please help me to get the data across.
Thank you.
What you're trying to do is to redirect to the same page with an additionnal variable. But it can't work like that.
A simple answer would be this:
web.php
Route::get('orders/show/all', 'OrderController#showOrders')->name('orders.show.all');
Controller.php
public function showOrders(){
$orders = Order::orderBy('total_amount', 'desc')
->where('user_id','=', Auth::user()->id)
->get();
// I have added the same condition. I believe, you don't want the user to be able to see all user's orders
$ordered_item = Order::where('user_id', '=', Auth::user()->id)
->find(request('order_id'));
return view('orders.undo_sales', compact('orders', 'ordered_item'));
}
}
blade.php
....
Order details
....
#if($ordered_item)
<aside class="col-sm-4" id="aside">
#foreach ($ordered_item->items as $value)
....
#endforeach
</aside>
#endif

How to show checkbox selected values in the same laravel view before submitting the form?

I have create.blade.php view. And that view showing a table with checkbox in each row. Now I want to show the checked row on the same view next to this table. Till now what I am getting the all the checked values but how can show it the same view before sending any post request to the server.
Here is some code-
#if(count($movies) > 0)
<div class="table-responsive">
<table class="table table-striped table-hover" data-toggle="dataTable"
data-form="deleteForm">
<thead>
<tr>
<th></th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
<label>Select movies</label>
#foreach($movies as $movie)
<tr>
<td>
<input class="form-check" type="checkbox" name="movie_cb" id=" .
{{$movie->id}}" value="{{$movie->name}}">
</td>
<td>{{$infeedVideo->name}}</td>
</tr>
#endforeach
</tbody>
</table>
#else
<div class="text-center">
<hr>
<p class="text-center">No movies found</p>
</div>
#endif
app.blade.php
<script type="text/javascript">
$(document).ready(function() {
$("#showCBs").click(function(){
var favorite = [];
$.each($("input[name='movie_cb']:checked"), function(){
favorite.push($(this).val());
});
alert("My favourite movies are: " + favorite.join(", "));
});
});
</script>
Now how can I pass the favorite array from app.blade.php to my laravel view create.blade.php. Thank you

I am trying to pass user id from my blade template to Vue for Axios post request to the server

However when I click the button only the first button contains the user id the rest returns null. Also depending on where I place my id tag on HTML the data-id is empty. How can I pass data from my blade view to Vue.js for an Axios post request which contains the post Id ?
const app = new Vue({
el: '#like',
data: {
post_id: '',
},
methods: {
whichId: function(event) {
this.post_id = this.$el.getAttribute('data-id');
console.log(this.$el.getAttribute('data-id'));
}
}
})
<div class="container" id="like">
<table class="table mt-5">
<tbody>
#foreach ($posts as $post)
<tr>
<td><img src="images/profil.svg" class="rounded-circle border border-dark ml-2" width="60" height="60" alt=""></td>
<td>{{ $post->username->name }}</td>
<td>{{ $post->content }}</td>
<td>
<button v-on:click="whichId" data-id="{{ $post->id }}">
<img src="/images/heart.svg" width="30" height="30" />
</button>
</td>
<td>{{ $post->created_at->diffForHumans() }}</td>
</tr>
#endforeach
</tbody>
</table>
</div>
The this.$el is going to refer to the element. When using PHP to iterate through records. You should pass the id through the click event handler. Thanks to Wilk Randall on laracast for the help.
methods: {
whichId (postId) {
console.log(postId);
}
}
<td><button v-on:click="whichId({{ $post->id }})"<img src="/images/heart.svg" width="30"></button></td>

Laravel 5.4 and Vue.js 2.0 Emitted value instead of an instance of Error

I'm having hard time on this.
My specific error is on this code: If I'll try to remove it everything works but I need to display the data columns. I don't understand why it cause an error.
<select>
<option v-for="column in columns">{{ column }}</option>
</select>
My app.js
import Vue from 'vue'
import DataViewer from './components/DataViewer.vue'
const app = new Vue({
el: '#app',
components: {
DataViewer
},
data: {
}
});
My DataViwer.vue
<template>
<div class="dv">
{{ title }}
</div>
<select>
<option v-for="column in columns">{{ column }}</option>
</select>
</template>
<script type="text/javascript">
import Vue from 'vue'
import axios from 'axios'
export default {
props: ['source', 'title'],
data(){
return {
model: {},
columns: {}
}
},
created(){
this.fetchIndexData()
},
methods: {
fetchIndexData(){
var vm = this
axios.get(this.source)
.then(function(response){
Vue.set(vm.$data, 'model', response.data.model)
Vue.set(vm.$data, 'columns', response.data.columns)
console.log(vm.$data.columns);
})
.catch(function(response){
console.log(response)
})
}
}
}
</script>
My ajax results:
I had the same warn and I found this decision: http://github.com.proxy.parle.co/ElemeFE/element/issues/4137
<el-tag v-for="tag in tags">
=>
<el-tag v-for="(tag, index) in tags" :key="index">
I faced that error because of a syntax mistake in for loop
the problem was the typo issue in src attribute in img tag!
<img class="m-widget__img" src="{{article.img_thumbnail}}" alt="">
which is totally wrong! it have to be like:
<img class="m-widget__img" :src="article.img_thumbnail" alt="">
as you know in these cases we have to bind the parameter to use in that attribute,
so first of all search for similar mistakes...
hope be helpful
To give Vue a hint so that it can track each node’s identity, and thus reuse and reorder existing elements, you need to provide a unique key
<option v-for="column in columns">{{ column }}</option>
change it to
<option v-for="column in columns" :key="column">{{ column }}</option>
I have the same warn and figure it out that it happen when writing something else outside the loop:
This is OK
<template>
<table class="responsive-table">
<thead>
<tr>
<th class="no-print" style="width:1%;">
<label>
<input type="checkbox" v-model="selectAll"><span></span>
</label>
</th>
<th style="width:85%">Fecha</th>
<th style="width:14%">Acciones</th>
</tr>
</thead>
<tbody>
<tr v-for="list in messages" :key="list.id">
<td class="no-print" style="width:1%;">
<label><input type="checkbox" name="print_messages[]" v-model="selected" :value="list.id"><span></span></label>
</th>
<td class="view-link">{{list.formatted_date}}</td>
<td></td>
</tr>
</tbody>
</table>
This is NOT OK and through the error "(Emitted value instead of an instance of Error)"
<template>
<h1>I AM TRYING TO ADD A TITLE IN HERE</h1>
<table class="responsive-table">
<thead>
<tr>
<th class="no-print" style="width:1%;">
<label>
<input type="checkbox" v-model="selectAll"><span></span>
</label>
</th>
<th style="width:85%">Fecha</th>
<th style="width:14%">Acciones</th>
</tr>
</thead>
<tbody>
<tr v-for="list in messages" :key="list.id">
<td class="no-print" style="width:1%;">
<label><input type="checkbox" name="print_messages[]" v-model="selected" :value="list.id"><span></span></label>
</th>
<td class="view-link">{{list.formatted_date}}</td>
<td></td>
</tr>
</tbody>
</table>
** CHECK THE FIRST LINE AFTER OPENING "template" tag
Any clue on this?
Oh, BTW, I am learning VUEJS brute force style... so be nice ;p
In my case the problem was writing this:
<div :v-if="a>b"/>
<div v-else/>
Instead of this:
<div v-if="a>b"/>
<div v-else/>
Afaik you usually get this error when you have made a syntactic error in your template. It has usually nothing to do with the javascript and logic of your application.

Resources