bootstrap-vue - table won't get updated after AJAX request (vue2.js) - javascript

I'm pretty new with vue.js and I saw this great library that doing exactly what I need for my project: Boostrap-Vue
example source code
I followed the basic instructions and I've added an small change, ajax call for dynamic content:
<layout :docs="docs">
<template slot="demo">
<b-table
stripped
hover
:items="items"
:fields="fields"
:current-page="currentPage"
:per-page="perPage"
:filter="filter"
>
<template slot="name" scope="item">
{{item.value.first}} {{item.value.last}}
</template>
</b-table>
</template>
</layout>
export default {
mounted () {
this.get_data();
},
data() {
return {
docs: {
component: 'bTable'
},
items: [],
fields: {
name: {label: 'Person Full name', sortable: true},
},
currentPage: 1,
perPage: 5,
filter: null
};
},
methods: {
get_data () {
this.$http.get("myapp/users").then(res => {
if (res.body) {
this.items = res.body;
} else {
this.error = true;
}
});
}
}
};
So the problem is - after I'm getting the Ajax response and the "items" variable initialized with the data but the table still won't get update.
The strangest part is that with static data its works fine (as shown in the example source code, without AJAX).
Any idea why?
Thanks!!!

I found the problem, it seems that it necessary to define the following fields according to the value I received in the response:
fields: {
name: {label: 'Person Full name', sortable: true},
}
so if my json looks like this:
{user_name: "user"}
it should look like this:
fields: {
user_name: {label: 'Person Full name', sortable: true},
}
Anyway, Yoram de Langen Thanks for the help!

Did you try to debug the res.body and what it contains? What is the structure your myapp/users returns? Do you return the structure directly like so:
[
{ "name": "item 1"},
{ "name": "item 1"},
]
or does it look like this:
{
"result": [
{ "name": "item 1"},
{ "name": "item 1"},
]
}
In case of the latest one your this.items = res.body should be: this.items = res.body.result

Related

use fetched info in an array in vue.js

I have this array:
data() {
return {
landingInfo: null,
slides: [
{
title: `this`,
},
{
title: "that",
},
{
title: "those",
},
],
};
},
Which is being displayed this way:
<div
class="slide"
v-for="(slide, index) in slides"
:key="index",
}"
>
<div>
<h1 class="text-bold">{{ slide.title }}</h1>
</div>
The problem is that I'm fetching info from and api and once I try to do:
slides: [
{
title: {{ landingInfo.data.subtitle }},
},
{
title: {{ landingInfo.data.subtitle2 }},
},
{
title: {{ landingInfo.data.subtitle3 }},
},
],
Everything explodes, I am new in vue using Nuxt.js and I cannot find any solution in how to achieve that.
Can someone show me how to include the fetched info inside the array property?
PD: I already tried using "{{thefetchedinfo}}" but it takes it literally that way and displays "{{thefetchedinfo}}"
The OP doesn't provide much info on the fetch, like when it is performed or what the returned data looks like, but the common pattern goes like this...
// <template> as in the OP, then...
data() {
return {
landingInfo: null,
slides: [], // empty before the fetch
};
},
mounted () {
fetchFromTheAPI().then(landingInfo => {
// More commonly, you'd map over the returned data to form slides,
// or, trying to match the OP...
this.slides = [
{ title: landingInfo.data.subtitle },
{ title: landingInfo.data.subtitle2 }, // ... and so on
]
});
},

Bootstrap Modal popup component not working on click of angular formly element

I have a reuquirement in which i am using a multiselect of angular formly which also has logo for each row. On click of this logo i want to load modal popup component, i am following a Stackblitz Demo for calling modal-component in app.component on click of element.
The link of demo which i followed : Bootstrap modal Stackblitz Demo
My workaround demo which i am implenenting is as follows : Workaround Demo Stackblitz
The error which i am getting on click of logo with the function openModal() is of undefined object.
How to i rectify this while working with angular formly?
Following is the snippet of the code:
multiselect formly component
#Component({
selector: 'formly-field-multiselect',
template: `<br><p-multiSelect [options]="to.options"
[formControl]="formControl"
[formlyAttributes]="field"
[showClear]="!to.required" >
<ng-template let-item pTemplate="item">
<div>{{item.label}}</div>
<div>
<i class="pi pi-check" (click)="to.openModal()"></i>
</div>
</ng-template>
</p-multiSelect>
`,
})
app.component.ts in which modal component(calenderComponent) is called
fields: FormlyFieldConfig[] = [
{
key: "select",
type: "multiselect",
templateOptions: {
multiple: false,
placeholder: "Select Option",
options: [
{ label: "Select City", value: null },
{ label: "New York", value: { id: 1, name: "New York", code: "NY" } },
{ label: "Rome", value: { id: 2, name: "Rome", code: "RM" } },
{ label: "London", value: { id: 3, name: "London", code: "LDN" } },
{
label: "Istanbul",
value: { id: 4, name: "Istanbul", code: "IST" }
},
{ label: "Paris", value: { id: 5, name: "Paris", code: "PRS" } }
],
openModal() {
this.modalRef = this.modalService.show(CalenderComponent, {
initialState: {
title: 'Modal title'
}
});
},
}
}
If you debug this, you can see that this in the context of your function (openModal), is the field you defined in the fields object, which doesnt have the modalService service you injected to the component, to overcome this, you can use a lambda expression:
openModal: () => {
this.modalRef = this.modalService.show(CalenderComponent, {
initialState: {
title: "Modal title"
}
});
}
this keeps the closure as you wanted, you can read more about it here
After you solve that problem, you will face another one:
To overcome this, you need to add the CalenderComponent as an entrycomponent in your app module file (app.module.ts):
entryComponents: [CalenderComponent]
Here is a forked working stackblitz

selectize.js and vue.js 2 ajax loaded optons

I'm using vuejs#2.3.3, selectize#0.12.4, vue2-selectize.
I have a pretty big form with a few select inputs.
All options are loaded by ajax into a one property, which is initialized with a demo data before being replaced by ajax data:
addTrackData : {
styles : [
{ id: 1, title: 'style 1' },
{ id: 2, title: 'style 3' },
{ id: 3, title: 'style 2' },
],
authors: [
{inn: '111', name: 'demo 1'},
{inn: '222', name: 'demo 2'},
{inn: '333', name: 'demo 3'}
]
....
},
And I've got 2 problems:
1) If I use settings in this way, options doesn't loads at all:
<selectize v-model="form.data.authors[i]['id']" :settings="selectize.authors"></selectize>
selectize: {
authors: {
valueField: 'inn',
labelField: 'name',
searchField: ['name', 'inn'],
options: this.addTrackData.authors // that doesn't works, but hard coded array works
}
}
Because of error Error in data(): "TypeError: Cannot read property 'authors' of undefined".
Both this.addTrackData.authors and addTrackData.authors makes this error.
But this way works:
<selectize v-model="form.data.authors[i]['id']"
:settings=" {
valueField: 'inn',
labelField: 'name',
searchField: ['name', 'inn'],
options: addTrackData.authors, // It works, but looks too ugly!
}" >
</selectize>
2) Options are not reactive - when ajax data comes, all selects elements still shows a demo data. And I have no idea how to update them all...
UPDATE
Second problem could be fixed with If Conditional and empty initial array:
<selectize v-if="addTrackData.authors.length" v-model="form.data.authors[i]['id']"
:settings=" {
valueField: 'inn',
labelField: 'name',
searchField: ['name', 'inn'],
options: addTrackData.authors, // It works, but looks too ugly!
}" >
</selectize>
addTrackData : {
styles : [],
authors: []
....
}
But the first problem still makes me cry
I just read the source code of vue2-selectize and noticed that it's watch code for options key is incorrect.
his code is this way:
watch: {
value() {
this.setValue()
},
options (value, old) {
if (this.$el.selectize && !equal(value, old)) {
this.$el.selectize.clearOptions()
this.$el.selectize.addOption(this.current)
this.$el.selectize.refreshOptions(false)
this.setValue()
}
}
},
while it should be this way to work:
watch: {
value() {
this.setValue()
},
options (value, old) {
if (this.$el.selectize && !equal(value, old)) {
this.$el.selectize.clear();
this.$el.selectize.clearOptions();
var vm = this;
this.$el.selectize.load(function(callback) {
callback(vm.current);
});
this.$el.selectize.refreshOptions(false);
this.setValue();
}
}
},
I just prepared a hacky way to make it working but I dont encourage you using it in production.
Here is the fiddle's link: https://jsfiddle.net/ahmadm/h8p97hm7/
I'll try to send a pull request to his creator as soon as possible but until that time, your solution is already the only possible solution.

Make a Tree view from JSON data using React JS

First of all i am very new to React JS. So that i am writing this question. I am trying this for three days.
What I have to do, make a list of category, like-
Category1
->Sub-Category1
->Sub-Category2
Categroy2
Category3
.
.
.
CategoryN
And I have this json data to make the listing
[
{
Id: 1,
Name: "Category1",
ParentId: 0,
},
{
Id: 5,
Name: "Sub-Category1",
ParentId: 1,
},
{
Id: 23,
Name: "Sub-Category2",
ParentId: 1,
},
{
Id: 50,
Name: "Category2",
ParentId: 0,
},
{
Id: 54,
Name: "Category3",
ParentId: 0,
},
];
I have tried many open source examples, but their json data format is not like mine. so that that are not useful for me. I have build something but that is not like my expected result. Here is my jsfiddle link what i have done.
https://jsfiddle.net/mrahman_cse/6wwan1fn/
Note: Every subcategory will goes under a category depend on "ParentId",If any one have "ParentId":0 then, it is actually a category, not subcategory. please see the JSON
Thanks in advance.
You can use this code jsfiddle
This example allows to add new nested categories, and do nested searching.
code with comments:
var SearchExample = React.createClass({
getInitialState: function() {
return {
searchString: ''
};
},
handleChange: function(e) {
this.setState({
searchString: e.target.value.trim().toLowerCase()
});
},
isMatch(e,searchString){
return e.Name.toLowerCase().match(searchString)
},
nestingSerch(e,searchString){
//recursive searching nesting
return this.isMatch(e,searchString) || (e.subcats.length && e.subcats.some(e=>this.nestingSerch(e,searchString)));
},
renderCat(cat){
//recursive rendering
return (
<li key={cat.Id}> {cat.Name}
{(cat.subcats && cat.subcats.length) ? <ul>{cat.subcats.map(this.renderCat)}</ul>:""}
</li>);
},
render() {
let {items} = this.props;
let {searchString} = this.state;
//filtering cattegories
if (searchString.length) {
items = items.filter(e=>this.nestingSerch(e,searchString))
console.log(items);
};
//nesting, adding to cattegories their subcatigories
items.forEach(e=>e.subcats=items.filter(el=>el.ParentId==e.Id));
//filter root categories
items=items.filter(e=>e.ParentId==0);
//filter root categories
return (
<div>
<input onChange={this.handleChange} placeholder="Type here" type="text" value={this.state.searchString}/>
<ul>{items.map(this.renderCat)}</ul>
</div>
);
}
});

Kendo Grid: Group by first element in a list

So I'm working with a Kendo Grid and how it's headers are grouped. One option that I have working currently is for the Grid to grab my list and sort group by checking every element in that list. So I get something like:
->Roles:
->Roles: Tester, Manager, Team Lead
->Roles: Tester
->Roles: CEO, Tester
->Roles: Team Lead, CEO
(you get the idea). This is because "Roles" in my database model are in a list (since a person can have many roles) and the Kendo Grid is comparing every element in that list. However, I want it to group by just the first element in each person's list so I instead get something like:
->Roles: Tester
->Roles: Manager
->Roles: Team Lead
->Roles:
->Roles: CEO
etc. Does anyone know how to do this? Currently I am doing
group: {
field: "RoleName",
aggregates: [
{ field: "ResourceName", aggregate: "count" },
{ field: "OrganizationName", aggregate: "count" }
]
},
And I assume that I want to be doing something more along the lines of:
group: {
field: "RoleName.get(0)",
aggregates: [
{ field: "ResourceName", aggregate: "count" },
{ field: "OrganizationName", aggregate: "count" }
]
},
However, I'm not familiar enough with Kendo Grid to know the syntax to do this correctly. Thanks in advance for all help!
Edit: I should add that because many of the people that will be using this still need IE8 support, I am using Kendo Grid imports from /2012.2.710 instead of the latest update
*Edit My Answer assumes the user loads the data outside the function and doesn't hard code in the data.
Try using the parse function in schema,
I'll just add to what you should have in your project already, for example:
$('.grid').kendoGrid({
dataSource: {
schema: {
parse: function(data) {
for (var i = 0; i < data.length; i++) {
data[i].firstWord = data[i].name.split(' ')[0];
}
return data;
}
}
group: {
field: "firstWord"
}
},
columns: [{
field: "name"
}, {
field: "firstWord",
hidden: true,
groupHeaderTemplate: "#=value#"
}]
});
This is just a fix over Ryan Hoyle answer's example:
var grid = $('#grid').kendoGrid({
dataSource: {
data: [{
name: 'Hello world'
}, {
name: 'Hello John Doe'
}, {
name: 'Hello Jane Doe'
}, {
name: 'Bye Jane Doe'
}, {
name: 'Bye World'
}],
schema: {
parse: function(data) {
data.forEach(d => d.firstWord = d.name.split(' ')[0]);
return data;
}
},
group: {
field: "firstWord"
}
},
columns: [{
field: "name"
}, {
field: "firstWord",
hidden: true,
groupHeaderTemplate: "#=value#"
}]
}).data().kendoGrid;
<link href="http://kendo.cdn.telerik.com/2016.2.607/styles/kendo.common.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2016.2.607/js/kendo.all.min.js"></script>
<div id="grid"></div>

Categories