Kendo UI sortable template rendering incorrectly - kendo-ui

In this plunk I have two tables, the first one displays the data using *ngFor, and the second shows the same data but using kendo-sortable and a template. The sortable function works fine, but there are two problems. First, all the data are below the first column. Second, the index variable is undefined. Any ideas how to fix this?
#Component({
selector: 'my-app',
template: `
WITHOUT kendo-sortable
<table border="1">
<tr>
<td><b>Index</b></td>
<td><b>First Name</b></td>
<td><b>Last Name</b></td>
</tr>
<tr *ngFor="let item of items; let i = index">
<td style="width:50px">{{ i }}</td>
<td style="width:100px">{{ item.firstName }}</td>
<td style="width:100px">{{ item.lastName }}</td>
</tr>
</table>
<br><br>
WITH kendo-sortable
<table border="1">
<tr>
<td><b>Index</b></td>
<td><b>First Name</b></td>
<td><b>Last Name</b></td>
</tr>
<kendo-sortable [data]="items">
<ng-template let-item="item" let-rowIndex="i">
<tr>
<td style="width:50px">{{ i }}</td>
<td style="width:100px">{{ item.firstName }}</td>
<td style="width:100px">{{ item.lastName }}</td>
</tr>
</ng-template>
</kendo-sortable>
</table>
`,
encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
public items = [ {firstName: 'Joe', lastName: 'Don'},
{firstName: 'Jane', lastName: 'Dona'},
{firstName: 'Julius', lastName: 'Kent'}];
}

I changed the code a lot, so take a look at this:
import { Component } from '#angular/core';
import { products } from './products';
import { GridDataResult } from '#progress/kendo-angular-grid';
import { SortDescriptor, orderBy } from '#progress/kendo-data-query';
#Component({
selector: 'my-app',
template: `
<kendo-grid [data]="gridView" [height]="530>
<kendo-grid-column field="Index" title="Index" width="80"></kendo-grid-column>
<kendo-grid-column field="FirstName" title="First Name"></kendo-grid-column>
<kendo-grid-column field="LastName" title="Last Name" width="230"></kendo-grid-column>
</kendo-grid>
`
})
export class AppComponent {
public gridView: GridDataResult;
public products: any[] = products;
constructor() {
this.loadProducts();
}
private loadProducts(): void {
this.gridView = {
data: orderBy(this.products, this.sort),
total: this.products.length
};
}
}
Here you define the products in an external file and import them, this is the source for that. By doing what the ducumentation suggests, it might work for you :) Good luck!

Related

Datatable display problem using vue-axios and laravel

Im using jQuery datatables for displaying my data in my users component in Vue.js, but when I run my code it displays the data but it has some text that says "No data found". Can someone help me with this? I really don't have any idea because I'm new in this Frontend tools.
Users.vue:
<template>
<table id="table" class="table table-striped table-bordered">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>Type</th>
<th>Created</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users" :key="user.id">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.type }}</td>
<td>{{ user.created_at }}</td>
</tr>
</tbody>
</table>
</template>
<script>
export default {
data() {
return {
users: [],
form: new Form({
id: "",
name: "",
email: "",
password: "",
type: ""
})
};
},
methods: {
loadUsers() {
axios.get("api/user").then(({ data }) => (this.users = data));
}
},
created() {
console.log("Component mounted.");
this.loadUsers();
}
};
$(document).ready(function() {
$("#table").DataTable({});
});
</script>
Probably, you should init your widget DataTable after receiving data from api, more precisely in then method.
axios.get("api/user").then(({ data }) => {
this.users = data;
this.$nextTick(() => {
$("#table").DataTable({});
});
});
Explanation about Vue.$nextTick:
Defer the callback to be executed after the next DOM update cycle. Use
it immediately after you’ve changed some data to wait for the DOM
update. This is the same as the global Vue.nextTick, except that the
callback’s this context is automatically bound to the instance calling
this method.
axios.get("api/user").then(({ data }) => {
this.users = data;
$(function() {
$("#table").DataTable({});
});
});

Is there a way to update my component dynamically without refreshing the page?

I have a vue component which builds the card up, and within that component is another component that I pass data to with a prop I currently use Swal to as a popup to add a new project to the database however when it finishes adding I have to refresh the page for the data to be visible. The entire reason I wanted to use vue was to not have to refresh the page to view updated data and I haven't been able to figure it out.
This is my Projects.vue
import ProjectItem from './Projects/ProjectItem.vue';
export default {
name: "Projects",
components: {
ProjectItem
},
data() {
return {
projects: []
}
},
methods: {
getProjects () {
axios.get('/api/projects').then((res) => {this.projects = res.data});
},
addProject() {
Swal.queue([{
title: 'Add a New Project?',
html:
'<label for="name" style="color: #000;font-weight: 700">Project Name<input id="name" class="swal2-input"></label>' +
'<label for="description" style="color: #000;font-weight: 700">Project Description<textarea id="description" rows="5" cols="15" class="swal2-input"></textarea></label>',
showCancelButton: true,
confirmButtonText: 'Create Project',
showLoaderOnConfirm: true,
preConfirm: (result) => {
return new Promise(function(resolve, reject) {
if (result) {
let name = $('#name').val();
let desc = $('#description').val();
axios.post('/api/projects', {title:name,description:desc})
.then(function(response){
Swal.insertQueueStep({
type: 'success',
title: 'Your project has been created!'
})
resolve();
})
.catch(function(error){
Swal.insertQueueStep({
type: 'error',
title: 'Something went wrong.'
})
console.log(error);
reject();
})
}
});
}
}])
}
},
mounted () {
this.getProjects();
}
I bind it to ProjectItem in my Project.vue template:
<div class="table-responsive border-top">
<table class="table card-table table-striped table-vcenter text-nowrap">
<thead>
<tr>
<th>Id</th>
<th>Project Name</th>
<th>Team</th>
<th>Date</th>
<th>Preview</th>
</tr>
</thead>
<project-item v-bind:projects="projects" />
</table>
and this is my ProjectItem.vue:
<template>
<tbody>
<tr v-for="project in projects" :key="project.id">
<td>{{ project.id }}</td>
<td>{{ project.title }}</td>
<td><div class="avatar-list avatar-list-stacked">
{{ project.description }}
</div>
</td>
<td class="text-nowrap">{{ project.updated_at }}</td>
<td class="w-1"><i class="fa fa-eye"></i></td>
</tr>
</tbody>
</template>
<script>
export default {
name: "ProjectItem",
props: ["projects"],
}
</script>
You must insert the recently added project to the products array.
If you are able to change the backend code, you could change the response to include the project.
this.projects.push(response.project);

Loop array with vue in laravel

can anyone help me on the following problem please.
I'd like to run a simple array via a loop within vue in laravel to give all the array values out in a table. This is my code I adjusted from a tutorial I found in the internet: enter code here
<template>
<div>
<h1>Coffeetypes</h1>
<table class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr v-for="cctyp in cctypes" v-bind:key="cctyp.id">
<td>{{ cctyp.id }}</td>
<td>{{ cctyp.name }}</td>
<td>{{ cctyp.description }}</td>
<td><button class="btn btn-danger">Delete</button></td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
cctypes: [],
cctyp: {
id: '',
name: '',
description: '',
created_by: '',
updated_by: ''
},
id: '',
pagination: {},
edit: false
};
},
created() {
this.fetchCCTypes();
},
methods: {
fetchCCTypes(){
fetch('api/CCTypes')
.then(res => res.json())
.then(res => {
this.cctypes = res.data;
});
}
}
};
</script>
The problem is, that there is no filling in the table.
maybe it's the double .then()... in your fectch method ... you should console.log your data first ...

Checkbox doesn't save true value

I'm using Laravel 5.6 and Vuejs 2.
If I click on my checkbox and make the value true it's supposed to save a 1 in the database and if I click my checkbox and make the value false it saves a 0.
The problem I'm having is that if I click my checkbox and make it true, it doesn't save the correct value, no changes is made to the database and I don't get any errors. If I click on my checkbox and make it false, it saves the 0 correctly.
I did notice that even when my value is supposed to be true, I do get a false when I dd($category->has('active')
I'm not sure where I'm going wrong or how to fix it.
My vue file
<template>
<div class="card-body">
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Active</th>
<th scope="col">Title</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
<tr v-for="(category, index) in categoriesNew" >
<td>
<label>checkbox 1</label>
<input name="active" type="checkbox" v-model="category.active" #click="checkboxToggle(category.id)">
</td>
<td>
{{ category.title }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
props: ['categories'],
data(){
return {
categoriesNew: this.categories
}
},
methods: {
checkboxToggle(id){
console.log(id);
axios.put('/admin/category/active/'+id, {
categories: this.categoriesNew
}).then((response) => {
//Create success flash message
})
},
},
mounted() {
console.log('Component mounted.')
}
}
</script>
my routes
Route::put('admin/products/updateAll', 'Admin\ProductsController#updateAll')->name('admin.products.updateAll');
Route::put('admin/category/active/{id}', 'Admin\CategoryController#makeActive')->name('admin.category.active');
Route::resource('admin/category', 'Admin\CategoryController');
Route::resource('admin/products', 'Admin\ProductsController');
my CategoryController#makeActive
public function makeActive(Request $request, $id)
{
$category = Category::findOrFail($id);
if($request->has('active'))
{
$category->active = 1;
}else{
$category->active = 0;
}
$category->save();
}
I hope I made sense. If there is anything that isn't clear or if you need me to provide more info, please let me know
Try changing this line
categories: this.categoriesNew
to
categories: category.active
and add a data prop at the top called category.active: ''
I've managed to get it to work. This is what I did.
vue file
<template>
<div class="card-body">
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Active</th>
<th scope="col">Title</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
<tr v-for="(category, index) in categories" >
<td>
<label>checkbox 1</label>
<input type="checkbox" v-model="category.active" #click="checkboxToggle(category)">
</td>
<td>
{{ category.title }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
props: ['attributes'],
data(){
return {
categories: this.attributes,
}
},
methods: {
checkboxToggle (category) {
axios.put(`/admin/category/${category.id}/active`, {
active: !category.active
}).then((response) => {
console.log(response)
})
}
},
mounted() {
console.log('Component mounted.')
}
}
</script>
my routes
Route::put('admin/category/{category}/active', 'Admin\CategoryController#makeActive')->name('admin.category.active');
and my CategoryController#makeActive
public function makeActive(Request $request, $id)
{
$category = Category::findOrFail($id);
if(request('active') === true)
{
$category->active = 1;
}else{
$category->active = 0;
}
$category->save();
}

how to add filters and search in tables in vuejs?

I am learning vue js and building a SPA i want to know how do I add filters and search using an input tag. I also want to add a feature that when i click on a particular name on the table it should open the profile of that person also a select all functionality
<template>
<div class="animated fadeIn">
<input type="text" placeholder="Enter Name" v-model="searchText">
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>College Name</th>
<th>College City</th>
<th>Level Name</th>
<th>Submitted</th>
<th>Pending</th>
<th>Completed</th>
<th>Approved</th>
<th>Rejected</th>
</tr>
</thead>
<tbody>
<tr v-for="profile in profilesdata">
<td>{{profile.first_name}}</td>
<td>{{profile.college_name}}</td>
<td>{{profile.college_city}}</td>
<td>{{profile.level_name}}</td>
<td>{{profile.submitted}}</td>
<td>{{profile.pending}}</td>
<td>{{profile.complete}}</td>
<td>{{profile.approve}}</td>
<td>{{profile.rejected}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default{
name: 'profiles',
data () {
return{
profilesdata: []
}
},
created:function(){
this.loadlike()
},
methods:{
loadlike:function(){
this.$http.get('/api/profiles').then(function (res) {
this.profilesdata = res.body
console.log(53+this.profiles)
})}}}
</script>
you could probably return computed list instead of profilesData
<template>
...
<input type="text" placeholder="Enter Name" v-model="searchText">
...
<tr v-for="profile in computedProfilesData">
...
</template>
<script>
export default{
...
data () {
return {
...
// - you need info for searchText
searchText: ''
}
}
...
computed: {
computedProfilesData(){
let searchString = this.searchText;
return this.profilesdata.filter((profile) => {
// example
profile.first_name.indexOf(searchString) !== -1;
})
}
}
</script>
there is a lot of different ways to do this, this is just one of them.
you can pass that searchString to API and return result list, it all comes to that
what do you really need.
You can make a computed for the filtered data:
computed: {
filteredProfiles() {
return this.profilesdata.filter(profile => {
// TODO filter profile with this.searchText
})
}
}
And then change the v-for to loop over the filtered data: <tr v-for="profile in filteredProfiles">

Resources