I am building a Vue JS Application, with a Vuetify data-table, and an Algolia InstantSearch Vue Component into it. However currently the data-table, and the InstantSearch index are using different data sources.
How should I integrate the search results from the Algolia index into the Vuetify data-table?
<div id="App">
<v-app id="inspire" v-cloak>
<ais-index app-id="{{ config('scout.algolia.id') }}" index-name="{{ (new App\FoodCat)->searchableAs() }}"
api-key="{{ Algolia\ScoutExtended\Facades\Algolia::searchKey(App\FoodCat::class) }}">
<section id="widget-grid">
<div class="row">
<article class="col-xs-12 col-sm-12 col-md-12 col-lg-12 sortable-grid ui-sortable">
<div class="jarviswidget jarviswidget-sortable" id="wid-id-2" data-widget-editbutton="false" data-widget-deletebutton="false">
<header class="ui-sortable-handle">
<div class="widget-header">
<h2><i class="fa fa-list text-orange"></i> Food Categories List</h2>
</div>
<div class="widget-toolbar smart-form">
<label class="input">
<i class="icon-append fa fa-search"></i>
<ais-input placeholder="Search By Keyword"></ais-input>
</label>
</div>
<div class="widget-toolbar smart-form">
<label class="input"> <i class="icon-append fa fa-plus-square-o"></i>
<input v-model="form.inputs.title.val" type="text" class="form-control" :class="{ 'is-invalid': form.errors.title }" name="title" value="" :placeholder="(form.errors.title) ? 'Category Title Required' : 'Add Food Category'" />
</label>
</div>
<button class="btn btn-sm text-white bg-orange widget-hdr-btn" v-html="form.btnText" #click.prevent="(formMode == 'add') ? add() : save()"></button>
<button class="btn btn-sm btn-danger widget-hdr-btn" #click="deleteSelected"><span class="fa fa-trash"></span> Delete Selected</button>
</header>
<!-- widget div-->
<div role="content" class="widget-content no-padding">
<!-- widget content -->
<div class="widget-body">
<ais-results>
<template scope="{ result }">
<div>
<h1>#{{ result.title }}</h1>
<h4>#{{ result.slug }}</h4>
</div>
</template>
</ais-results>
<v-progress-linear :indeterminate="true" :height="3" color="#c79121" :active="loadingVal"></v-progress-linear>
<v-data-table v-model="selected" :headers="headers" :items="collection" :pagination.sync="pagination" select-all item-key="id" class="elevation-1" >
<template v-slot:headers="props">
<tr>
<th><v-checkbox :input-value="props.all" color="#c79121" :indeterminate="props.indeterminate" primary hide-details #click.stop="toggleAllSelected"></v-checkbox></th>
<th v-for="header in props.headers" :key="header.text"
:class="['column sortable', pagination.descending ? 'desc' : 'asc', header.value === pagination.sortBy ? 'active' : '']"
#click="changeSort(header.value)">
<v-icon small>arrow_upward</v-icon>
#{{ header.text }}
</th>
</tr>
</template>
<template v-slot:items="props">
<tr :active="props.selected" #click="props.selected = !props.selected">
<td class="text-center align-middle">
<v-checkbox :input-value="props.selected" primary hide-details color="#c79121"></v-checkbox>
</td>
<td class="text-center align-middle">#{{ props.item.id }}</td>
<td>#{{ props.item.title }}</td>
<td>#{{ props.item.slug }}</td>
<td class="text-right align-middle">
<button class="btn btn-primary btn-sm" #click="edit(props.item.id)"><span class="fa fa-edit"></span> Edit Food Category</button>
<button class="btn btn-danger btn-sm" #click="remove(props.item.id)"><span class="fa fa-trash"></span> Delete Food Category</button>
</td>
</tr>
</template>
<template slot="no-data">
<p class="text-xs-center">No Data</p>
</template>
</v-data-table>
</div>
</div>
</div>
</article>
</div>
</section>
</ais-index>
</v-app>
</div>
var app = new Vue({
el: '#App',
mixins: [ crudFunctionsMixin ],
data: () => ({
model: "food-cat",
modelName: "Food Category",
modelNamePlural: "Food Categories",
form: {
inputs: {
id: { val: '', save: true },
title: { val: '', save: true, add: true },
slug: { val: '', save: true, add: true },
},
btnText: "<i class='fa fa-plus-square-o'></i> Add Food Category",
errors: false
},
formSearch: {
inputs: {
keywords: ''
}
},
headers: [
{ text: 'ID', value: 'id', sortable: true },
{ text: 'Title', value: 'title', sortable: true },
{ text: 'Slug', value: 'slug', sortable: true },
{ sortable: false }
],
pagination: {
sortBy: 'title'
},
collection: []
}),
watch: {
},
methods: {
fetch() {
$.get(`/${this.model}/fetch`, (r) => {
if(r.successMsg) {
this.collection = r.collection;
}
});
}
}
});
app.fetch();
Related
I am developing a web page. there i am using v-modal with vuejs. I am making an object form new Form. it gets. in the html it inserts the id which is input by user but i want to replace that with the userID gotten from the currently logged in user. i tried getter and settter in the script but it does not change the form.id. it takes the input from user . the following is my code. sorry for the messy code.
<template>
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0">Applications Page</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><router-link to="/dashboard">Home</router-link></li>
<li class="breadcrumb-item active">About Page</li>
</ol>
</div>
</div>
</div>
</div>
<div class="content">
<div class="container-fluid">
<div class="row mt-4">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Application</h3>
<div class="card-tools">
<button class="btn btn-success" #click="newModal">Add New
<i class="fa-regular fa-calendar-plus fa-fw"></i>
</button>
</div>
</div>
<div class="card-body table-responsive p-0">
<table class="table table-hover text-nowrap">
<thead>
<tr>
<th>ID</th>
<th>User_ID</th>
<!-- <th>body</th> -->
<!-- <th>category_id</th> -->
<!-- <th>user_id</th> -->
<th>Job_ID</th>
<th>Status</th>
<!-- <th>image</th> -->
<th>Modify</th>
</tr>
</thead>
<tbody>
<tr v-for="application in applications.data" :key="application.id">
<td> {{ application.id }}</td>
<td>{{ application.user_id }}</td>
<td>{{ application.job_id }}</td>
<td> {{ application.status }}</td>
<td>
<a href="#" #click="editModal(application)">
<i class="fa fa-edit blue"></i>
</a> /
<a href="#" #click="deleteApplication(application.id)">
<i class="fa fa-trash red"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" v-show="!editmode" id="myModalLabel">Add New Application</h1>
<h1 class="modal-title fs-5" v-show="editmode" id="myModalLabel">Udate Application</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form #submit.prevent="editmode ? updateApplication() : createApplication() ">
<div class="modal-body">
<div class="form-group">
<input v-model="form.user_id" type="text" name="user_id" placeholder="user_id"
class="form-control" :class="{ 'is-invalid': form.errors.has('user_id') }">
<has-error :form="form" field="user_id"></has-error>
</div>
<!-- <input :value="userID" > -->
<!-- <div class="form-group"></div> -->
<!-- <select v-model="form.user_id">
<option :value=userID.id></option>
</select>
</div> -->
<!-- <input v-model="form.user_id" type="text" name="user_id" placeholder="user_id"
class="form-control" :class="{ 'is-invalid': form.errors.has('user_id') }"> <has-error :form="form" field="user_id"></has-error> -->
<div class="form-group">
<textarea v-model="form.job_id" type="text" name="job_id" placeholder="job_id"
class="form-control" :class="{ 'is-invalid': form.errors.has('job_id') }"></textarea>
<has-error :form="form" field="job_id"></has-error>
</div>
<div class="form-group">
<input v-model="form.status" type="text" name="status" placeholder="status"
class="form-control" :class="{ 'is-invalid': form.errors.has('status') }">
<has-error :form="form" field="status"></has-error>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">Close</button>
<!-- <button type="submit" class="btn btn-primary" data-bs-dismiss="modal">Create</button> -->
<button v-show="editmode" type="submit" class="btn btn-success">Update</button>
<button v-show="!editmode" type="submit" class="btn btn-primary">Create</button>
</div>
</form>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
import Form from 'vform';
import Swal from 'sweetalert2/dist/sweetalert2.js';
import 'sweetalert2/src/sweetalert2.scss';
export default {
data: () => ({
editmode: false,
applications: {},
// catIDs: {},
userID: {},
form: new Form({
id: '',
user_id: '',
job_id: '',
status: '',
// get newUserID (){
// return this.user_id;
// },
// set newUserID(newUser_id){
// this.user_id = newUser_id[0];
// }
})
}),
methods: {
updateApplication(id) {
this.form.put('api/application/' + this.form.id)
.then(() => {
$('#myModal').modal('hide');
Swal.fire('Application updated!');
// this.$emit('afterCreate');
this.loadApplication();
})
.catch(() => {
Swal.fire({
icon: 'error',
title: 'Oops...',
text: 'Something went wrong!',
})
});
},
newModal() {
this.editmode = false;
this.form.reset();
$('#myModal').modal('show');
},
editModal(application) {
this.editmode = true;
this.form.reset();
$('#myModal').modal('show');
this.form.fill(application);
},
deleteApplication(id) {
Swal.fire({
title: 'Are you sure?',
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
}).then((result) => {
if (result.isConfirmed) {
this.form.delete('api/application/' + id).then(() => {
Swal.fire(
'Deleted!',
'Application has been deleted.',
'success'
);
this.loadApplication();
}).catch((result) => {
Swal.fire({
icon: 'error',
title: 'Oops...',
text: 'Something went wrong!',
})
});
}
})
},
loadApplication() {
axios.get("api/application").then(({ data }) => (this.applications = data));
},
loadUserID() {
axios.get('api/applicationGetID').then(({ data }) => (this.userID = data));
console.log(this.form.user_id);
// axios.get('api/applicationGetID').then(({ data }) => (this.userID2 = data.[id]));
},
// loadCatId() {
// axios.get('api/categoryId').then(({ data }) => (this.catIDs = data));
// },
createApplication() {
// this.form.newUserID = this.userID;
console.log(this.form.user_id)
this.form.post('api/application')
.then(() => {
$('#myModal').modal('hide');
Swal.fire('Application created!')
this.loadApplication();
})
.catch(() => {
Swal.fire({
icon: 'error',
title: 'Oops...',
text: 'Something went wrong!',
})
})
}
},
created() {
this.loadApplication();
this.loadUserID();
// this.loadCatId();
}
}
</script>
I try to update my recipe which has collection of ingredients(formArray) and i have problem with that because of formArray.
I have error on console:
ERROR Error: formArrayName must be used with a parent formGroup directive
When i update recipe without formArray(ingredients) it's working fine.
Could you give me a hint ?
It's my first time when i'm working with formArrays..
My code:
Component.ts
export class RecipeEditComponent implements OnInit {
#ViewChild('editForm') editForm: NgForm;
recipe: IRecipe;
photos: IPhoto[] = [];
ingredients: IIngredient[] = [];
uploader: FileUploader;
hasBaseDropZoneOver = false;
baseUrl = environment.apiUrl;
currentMain: IPhoto;
constructor(private route: ActivatedRoute, private recipeService: RecipeService,
private toastr: ToastrService) { }
ngOnInit(): void {
this.loadRecipe();
}
Html
<div class="container mt-4 border" *ngIf="recipe">
<form #editForm="ngForm" id="editForm" (ngSubmit)="updateRecipe(recipe.id)" >
<h5 class=" text-center mt-2">Recipe details:</h5>
<div class="form-group mt-3">
<label for="city">Name</label>
<label for="city">{{recipe.id}}</label>
<input class="form-control" type="text" name="name" [(ngModel)]="recipe.name">
</div>
<div class="form-group">
<div formArrayName="ingredients"
*ngFor="let ingredient of recipe.ingredients; let i = index;">
<div formGroupName= {{i}} class="row">
<div class="form-group col-6">
<app-text-input formControlName="name" [label]='"Name"' name="ingredient[i].name"></app-text-input>
</div>
<div class="form-group col-6">
<app-text-input formControlName="amount" [label]='"Amount"' [type]="'number'" name="ingredient[i].amount"></app-text-input>
</div>
</div>
</div>
</div>
<h5 class=" text-center mt-4">Description</h5>
<angular-editor cols=100% rows="6" [placeholder]="'Your description'" [(ngModel)]="recipe.description" name="description"></angular-editor>
</form>
<h3 class="text-center">Photos</h3>
<div class="row">
<div class="col-sm-2" *ngFor="let photo of recipe.recipePhotos">
<img src="{{photo.url}}" class="img-thumbnail p-1" alt="">
<div class="text-center">
<button type="button" class="btn btn-sm mr-1 mb-2"
(click) = "setMainPhoto(photo)"
[disabled]="photo.isMain"
[ngClass] = "photo.isMain ? 'btn-danger active' : 'btn-secondary'"
>Main</button>
<button type="button" class="btn btn-sm btn-danger mb-2"
(click)="deletePhoto(photo.id)" >
<i class="fa fa-trash-o"></i></button>
</div>
</div>
</div>
<div class="row justify-content-md-center mt-5 border">
<div class="col col-sm-4">
<div class="mt-4 text-center">
Multiple
<input type="file" ng2FileSelect [uploader]="uploader" multiple="true" /><br/>
Single
<input type="file" ng2FileSelect [uploader]="uploader" />
</div>
</div>
<div class="col col-sm-6">
<div ng2FileDrop
[ngClass]="{'nv-file-over': hasBaseDropZoneOver}"
(fileOver)="fileOverBase($event)"
[uploader]="uploader"
class="card bg-faded p-3 text-center mt-3 mb-3 my-drop-zone">
<i class="fa fa-upload fa-3x"></i>
Drop Photos Here
</div>
</div>
</div>
<div class="col-md-6 mt-5" style="margin-bottom: 40px" *ngIf="uploader?.queue?.length">
<h3 class="text-center">Upload queue</h3>
<p>Queue length: {{ uploader?.queue?.length }}</p>
<table class="table">
<thead>
<tr>
<th width="50%">Name</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of uploader.queue">
<td><strong>{{ item?.file?.name }}</strong></td>
<td *ngIf="uploader.options.isHTML5" nowrap>{{ item?.file?.size/1024/1024 | number:'.2' }} MB</td>
<td *ngIf="uploader.options.isHTML5">
</tr>
</tbody>
</table>
<div>
<div>
Queue progress:
<div class="progress mb-4" >
<div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': uploader.progress + '%' }"></div>
</div>
</div>
<button type="button" class="btn btn-success btn-s"
(click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length">
<span class="fa fa-upload"></span> Upload
</button>
<button type="button" class="btn btn-warning btn-s"
(click)="uploader.cancelAll()" [disabled]="!uploader.isUploading">
<span class="fa fa-ban"></span> Cancel
</button>
<button type="button" class="btn btn-danger btn-s"
(click)="uploader.clearQueue()" [disabled]="!uploader.queue.length">
<span class="fa fa-trash"></span> Remove
</button>
</div>
</div>
<button [disabled]="!editForm.dirty" form="editForm" class="btn btn-success btn-block mb-5 mt-5">Save changes</button>
</div>
This is how my recipe looks like with properties:
Problem Description
The directive formArrayName is a ReactiveForm directive and for it to work you must have below satisfied
Must have a parent formGroup
You must have imported ReactiveFormModule in your module
Solution
You may have to do some changes to implement this, see below
See Demo On Stackblitz
name = 'Angular ' + VERSION.major;
recipe = {
id: 1,
name: 'Test Recipe',
ingredients: [{
name: 'Chicken',
amount: 5
},
{
name: 'Pasta',
amount: 50
}],
description: 'Test Description'
}
ngForm = this.fb.group({
description: [this.recipe.description],
name: [this.recipe.name],
ingredients: this.fb.array(
this.recipe.ingredients.map(
ingredient => this.fb.group({
name: [ingredient.name],
amount: [ingredient.amount]
})
)
)
})
updateRecipe() {
}
<form [formGroup]="ngForm" id="editForm" (ngSubmit)="updateRecipe()">
<h5 class=" text-center mt-2">Recipe details:</h5>
<div class="form-group mt-3">
<label for="city">Name</label>
<label for="city">{{recipe.id}}</label>
<input class="form-control" type="text" formControlName='name'>
</div>
<div class="form-group">
<div formArrayName="ingredients" *ngFor="let ingredient of recipe.ingredients; let i = index;">
<div formGroupName={{i}} class="row">
<div class="form-group col-6">
<app-text-input formControlName="name" [label]='"Name"' name="ingredient[i].name">
</app-text-input>
</div>
<div class="form-group col-6">
<app-text-input formControlName="amount" [label]='"Amount"' [type]="'number'"
name="ingredient[i].amount"></app-text-input>
</div>
</div>
</div>
</div>
<h5 class=" text-center mt-4">Description</h5>
<angular-editor cols=100% rows="6" [placeholder]="'Your description'"
formControlName='description'></angular-editor>
</form>
Instead of using FormArrays in your template, try using NgModel for input data-binding:
<div class="form-group" *ngFor="let ingredient of recipe.ingredients; let i = index;">
<div class="form-group col-6">
<input [(ngModel)]="ingredient.name" />
</div>
<div class="form-group col-6">
<input [(ngModel)]="ingredient.amount" />
</div>
</div>
I have a array of objects(comments from posts kind like facebook comments or any other social network) and I iterate it with an v-for, then I have on each comment a dropdown button with "edit" and "delete" buttons, I would like that when I press the edit button the comment would change to an input so I can edit it, so I added a property click_to_edit initialize in false to each comment object, so when I click on edit it changes the condition that the v-for is related to. But it does not change it, I guess it is that as the property is inside an object it always return false and therefore the condition never changes, but I do not know how else do this. This is the html for the v-for:
<div
class="mb-2"
v-bind:class="'comment_'+post.id"
v-for="(comment, index) in comments"
:key="index"
v-if="comment.id_post === post.id"
>
<div class="row">
<div class="col-img-user-post text-center">
<img
class="rounded-circle img-icon-profile"
:src="routes.user_files+'/'+comment.code+'/'+comment.picture"
alt
/>
</div>
<div class="col">
<div class="row">
<div class="col">
<div class="card-comment">
<div class="row">
<div v-if="!comment.clicked_to_edit" class="col">
<p class="mt-2 mb-2">{{ comment.description }}</p>
<p class="mb-0 font-smaller grey-color">{{ comment.time_ago }}</p>
</div>
<div v-if="comment.clicked_to_edit" class="col">
<input v-model="comment.description" type="text" />
<p class="mb-0 font-smaller grey-color">{{ comment.time_ago }}</p>
</div>
<div class="col-1">
<div class="row dropdown">
<div class="col">
<a
class="font-smaller"
type="button"
:id="'dropdownMenuButtonComment_'+index"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<i class="fas fa-lg fa-angle-down grey-color"></i>
</a>
<div
class="dropdown-menu dropdown-menu-right"
:aria-labelledby="'dropdownMenuButtonComment_'+index"
>
<button
class="dropdown-item"
v-if="comment.id_user===profile_info.id_user"
#click="editComment(comment.id, index)"
>
<i class="far fa-edit"></i>
Edit
</button>
<button
class="dropdown-item"
data-toggle="modal"
data-target="#modalDeleteComment"
v-if="comment.id_user===profile_info.id_user"
#click="actionComment(comment.id, 2, index)"
>
<i class="far fa-trash-alt red-color"></i>
<span class="red-color">Delete</span>
</button>
<button
class="dropdown-item"
v-if="comment.id_user!==profile_info.id_user"
#click="actionComment(comment.id, 3)"
>
<i class="far fa-flag"></i>
Report
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
The object comment stated in the data:
comment: {
id: "",
id_post: "",
description: "",
clicked_to_edit: false,
id_user: this.profile_info.id_user,
code: this.profile_info.code,
name: this.profile_info.name,
surname_1: this.profile_info.surname_1,
surname_2: this.profile_info.surname_2,
nick: this.profile_info.nick,
picture: this.profile_info.picture,
role: this.profile_info.id_role,
time_ago: "0 minutes"
},
and the edit function:
editComment(id, index) {
this.comments[index].clicked_to_edit = true;
console.log(this.comments[index]);
},
I purposefully ignored your model, to show a general case. If you need help applying it to your case, let me know.
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
data: () => ({
comments: [
{ id: 'one', description: "test 1" },
{ id: 'two', description: "test 2" },
{ id: 'three', description: "test 3" }
].map(i => ({ ...i,
isEditing: false
}))
}),
methods: {
async toggleEditing(comment, index) {
const isOpening = !comment.isEditing;
this.comments
.filter(c => c.isEditing)
.forEach(c => c.isEditing = false);
if (isOpening) {
comment.isEditing = true;
await this.$nextTick();
this.$refs.comments[index].querySelector('input').focus()
}
},
blur: ev => ev.target.blur()
}
})
.comment {
min-height: 21px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(comment, i) in comments" ref="comments" :key="comment.id">
<div v-if="!comment.isEditing"
v-text="comment.description"
class="comment"
#click="toggleEditing(comment, i)"></div>
<div v-else>
<input v-model="comment.description"
#blur="toggleEditing(comment)"
#keyup.enter="blur"
/>
</div>
</div>
</div>
I have the following code snippet of my routes from app.js
let routes = [{
path: "/dashboard",
component: require("./components/Dashboard.vue")
},
{
path: "/tour",
component: require("./components/Index.vue"),
children: [{
name: 'create',
path: '/create',
component: require('./components/product/Create.vue')
}]
},
{
path: "*",
component: require("./components/NotFound.vue")
}
];
Master.blade.php
<div class="sidebar">
<router-link class="btn btn-success" to="/dashboard">
Dashboard
</router-link>
<router-link class="btn btn-success" to="/tour">
Tour
</router-link>
</div>
<div class="content">
<router-view></router-view>
</div>
Index.vue
<template>
<div class="container">
<div class="row mt-5">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Tours</h3>
<div class="card-tools">
<router-link class="btn btn-success" to="/tour/create">
Add New
<i class="fas fa-plus fa-fw"></i>
</router-link>
</div>
</div>
<!-- /.card-header -->
<div class="card-body table-responsive p-0">
<table class="table table-hover text-center">
<tbody>
<tr>
<th>ID</th>
<th>Name</th>
<th>Days</th>
<th>Price</th>
<th>Type</th>
<th>Image</th>
<th>Meta Title</th>
<th>Meta Description</th>
<th>Actions</th>
</tr>
<tr v-for="tour in tours.data" :key="tour.id">
<td>{{tour.id}}</td>
<td>{{tour.title}}</td>
<td>{{tour.days}}</td>
<td>{{tour.price}}</td>
<td>{{tour.category_id}}</td>
<td>
<i class="fas fa-check text-success" v-if="tour.image"></i>
<i class="fas fa-times text-danger" v-else></i>
</td>
<td>
<i class="fas fa-check text-success" v-if="tour.meta_title"></i>
<i class="fas fa-times text-danger" v-else></i>
</td>
<td>
<i class="fas fa-check text-success" v-if="tour.meta_description"></i>
<i class="fas fa-times text-danger" v-else></i>
</td>
<td>
<button #click="editModal(tour)" class="btn btn-primary btn-sm">Edit</button>
<button
#click="deleteUser(tour.id)"
class="btn btn-danger btn-sm"
>Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- /.card-body -->
<div class="card-footer"></div>
</div>
<!-- /.card -->
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
tours: ""
};
},
methods: {
initialLoad() {
axios.get("api/tour").then(({
data
}) => (this.tours = data));
}
},
created() {
this.initialLoad();
}
};
</script>
Index.vue shows all the tours that are saved in database.
Add New button is placed in Index.vue to load the Create.vue component in order to create tours.
But clicking on the create button loads NotFound.vue component from * route. No message of any type is given out during mixing and in console.
I also tried:
import create from './components/product/Create.vue';
and replacing component: require('./components/product/Create.vue') with create
And still no progress.
Can anyone point out the my mistake i'm doing here.
create a new file and Save by Tourview.vue inside the components folder.
<template>
<router-view ></router-view>
</div>
</template>
<script>
export default {
data() {
return {
};
},
methods: {
};
};
</script>
and update your routing file like following.
let routes = [{
path: "/dashboard",
component: require("./components/Dashboard.vue")
},
{
path: "/tour",
component: require("./components/Tourview.vue"),
children: [
{
path:'',
component: require("./components/Index.vue")
},
{
name: 'create',
path: '/create',
component: require('./components/product/Create.vue')
}]
},
{
path: "*",
component: require("./components/NotFound.vue")
}
];
I want to ask a question concerning vue-validator but it is not working on JSFiddle. Can someone please help me check what the issue is so that I can go ahead and ask the main question
See JSFiddle
Html:
<div id="app">
<validator name="instanceForm">
<form v-on:submit.prevent="addInstance()">
<div class="form-group">
<input id="'instancetext" type="text" class="form-control" placeholder="Enter new Instance" v-validate:instancetext="{ required: { rule: true, message: 'What is the instance ?'}}" v-model="todo.name">
<div class="errors" v-if="showErrors">
<span v-if="$instanceForm.instancetext.required">{{$instanceForm.instancetext.required}}</span>
</div>
</div>
<div class="form-group">
<button class="btn btn-default"> <i class="fa fa-plus"> </i> Add
</button>
</div>
</form>
</validator>
<div class="">
<div v-for="todo in todoStore" class="list-group">
<div class="list-group-item">
<h4>
Main Card
</h4> {{todo.name}} {{todo.id}}
</div>
<div class="list-group-item nopadding">
<button class="btn btn-xs btn-danger margin-10" v-on:click="todoDelete(todo)">
<i class=" fa fa-trash"></i>
</button>
<form #submit="addNoteInstance">
<div class="form-group">
<input id="note-#{{note.id}}" type="text" class="form-control" name="note-#{{note.id}}" placeholder="Enter new Note Instance" v-model="name">
<button type="submit"><i class="fa fa-plus"> Add Note Instance</i></button>
</div>
</form>
</div>
<div v-for="note in todoNoteStore" class="list-group nopadding nomargin">
<div v-if="todo.id == note.id">
<div class="list-group-item">
<h4>
Note fore card {{todo.id}}
</h4> {{note.id}}{{note.name}}
</div>
<div class="list-group-item nopadding">
<button class="btn btn-xs btn-danger margin-10" v-on:click="removeNoteInstance(note)">
<i class=" fa fa-trash"></i>
</button>
</div>
</div>
</div>
</div>
</div>
<pre>{{ $data | json }}</pre>
</div>
Js:
new Vue({
el: '#app',
data: function() {
return {
showErrors: false,
todo: {
id: 1,
name: '',
completed: false,
check: ''
},
todoNote: {
id: 1,
name: '',
completed: false,
check: ''
},
todoStore: [
],
todoNoteStore: [
]
}
},
methods: {
addInstance: function() {
if (this.$instanceForm.valid) {
this.todoStore.push(this.todo);
this.todo = {};
this.showErrors = false;
} else {
this.showErrors = true;
}
},
addNoteInstance: function(e) {
e.preventDefault();
this.todoNoteStore.push({
"id": 1,
"name": this.name,
"completed": false,
"check": ''
});
this.name = '';
},
removeNoteInstance: function(note) {
this.todoNoteStore.remove(note);
}
}
});
css:
.nopadding {
padding-top: 0px;
!important;
padding-bottom: 0px;
!important;
}
.nomargin {
margin: 0px;
}
There are two problems here.
The CDN you are using for Vue-Validator (v2.1.7) seems to be broken. The links for 2.1.6 and 3.0.0-alpha1 seem to be fine. (this is specifically referring to links on cdnjs)
Vue-Validator 2.x only works with Vue 1.x. Your CDN for Vue is pointing to Vue 2.0.3.
So, either use Vue 1.x and a a working version of Vue-Validator 2.x, or use Vue 2.x and Vue-Validator 3.x (which is currently in alpha).