Here is my Vue multiselect component:
<multiselect v-model="selectedcategoryitem"
:options="options"
:multiple="true"
:internal-search="false"
group-values="libs"
group-label="category"
:group-select="true"
placeholder="Type to search"
track-by="value"
label="name"
v-on:select="toggleSelected">
<span slot="noResult">Oops! No elements found. Consider changing the search query.</span>
</multiselect>
And data and method:
data: { selectGoalID: 0
, selectedcategoryitem: []
, queryData: []
, options: [
{
value: 1,
category: 'item1',
libs: [
{ value: "1_1", name: 'name1(E)' },
{ value: "1_2", name: 'name2(P)' },
{ value: "1_3", name: 'name3(T)' },
{ value: "1_4", name: 'name4(F)' },
{ value: "1_5", name: 'name5' },
]
},
{
value: 2,
category: 'item2',
libs: [
{ value: "2_1", name: 'name1' },
{ value: "2_2", name: 'name2' }
]
},
{
value: 3,
category: 'item3',
libs: [
{ value: "3_1", name: 'name1' },
{ value: "3_2", name: 'name2' },
{ value: "3_3", name: 'name3' },
{ value: "3_4", name: 'name4' },
{ value: "3_5", name: 'name5' },
]
},
}
, methods: {
UpdateType: function (goal_id, selectedTypes) {
return $.ajax({
method: "POST"
, url: "#Url.Action("UpdateType", "Predict")"
, data: {
_goal_id: goal_id,
_selectedTypes: selectedTypes
}
, success: function (result) {
if (result.code == "S") {
}
else {
alertResultModel(result);
}
},
error: function (xhr, ajaxOptions, thrownError) {
alertInfo(xhr.statusText);
}
});
}
, toggleSelected: function (value) {
if (value.length > 0) {
this.queryData = JSON.parse(JSON.stringify(value));
}
console.log(this.queryData);
this.UpdateType(this.selectGoalID, this.queryData).then(
function (result) {
if (result.code == "S") {
}
else {
alertResultModel(result);
}
}
, function () {
alertError("Error!!");
}
);
}
}
And when I selected single item, console log return: null,
When i selected multiple items console log return:
(2) [{…}, {…}, __ob__: Observer]
0: {__ob__: Observer}
1: {__ob__: Observer}
length: 2
__ob__: Observer {value: Array(2), dep: Dep, vmCount: 0}
[[Prototype]]: Array
Question is:
Why first selected item is null, but v-model="selectedcategoryitem" selectedcategoryitem.length is 1.
How to convert value to JSON format send to Backend.
Step 1: Create an HTML template
<div id="app">
<multiselect
v-model="selectedcategoryitem"
:options="options"
:multiple="true"
:internal-search="false"
group-values="libs"
group-label="category"
:group-select="true"
placeholder="Type to search"
track-by="value"
label="name"
#input="onChange"
>
</multiselect>
<p>Selected Item: {{ selectedcategoryitem }}</p>
</div>
Step 2: Model data like,
data() {
return {
selectGoalID: 0,
selectedcategoryitem: [],
options: [
{
value: 1,
category: "item1",
libs: [
{ value: "1_1", name: "name1(E)" },
{ value: "1_2", name: "name2(P)" },
{ value: "1_3", name: "name3(T)" },
{ value: "1_4", name: "name4(F)" },
{ value: "1_5", name: "name5" },
],
},
{
value: 2,
category: "item2",
libs: [
{ value: "2_1", name: "name1" },
{ value: "2_2", name: "name2" },
],
},
{
value: 3,
category: "item3",
libs: [
{ value: "3_1", name: "name1" },
{ value: "3_2", name: "name2" },
{ value: "3_3", name: "name3" },
{ value: "3_4", name: "name4" },
{ value: "3_5", name: "name5" },
],
},
],
};
},
Step 3: Create an methods and call REST API call
methods: {
UpdateType: function (goal_id, selectedTypes) {
console.log("selectedTypes", selectedTypes);
return $.ajax({
method: "POST",
url: "#Url.Action('UpdateType', 'Predict')",
data: {
_goal_id: goal_id,
_selectedTypes: JSON.stringify(selectedTypes),
},
success: function (result) {
alert(result);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.statusText);
},
});
},
onChange() {
console.log("this.selectedcategoryitem", this.selectedcategoryitem);
this.UpdateType(this.selectGoalID, this.selectedcategoryitem).then(
function (result) {
alert(result);
},
function () {
alert("Error!!");
}
);
},
},
You can see the logs for selected items and AJAX call form data
DEMO Link
Related
I have built a vue component to show a PIE chart in echart library as showed below. The PIE chart will be initialized with a default value.
pieChart.vue
<template>
<div :class="className" :style="{height:height,width:width}" />
</template>
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import resize from './mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '300px'
},
chartData: {
type: Object,
required: true
}
},
watch: {
chartData: function(val){
console.log('chartdata handler',val);
this.setOptions(val.legend, val.data);
}
},
data() {
return {
chart: null
}
},
mounted() {
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, 'macarons');
this.setOptions(
['group_a','group_b','group_c'],
[
{ value: 1, name: 'group_a' },
{ value: 2, name: 'group_b' },
{ value: 3, name: 'group_c' },
]
);
},
setOptions( lengend, data ) {
this.chart.setOption({
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
left: 'center',
bottom: '10',
data: lengend
},
series: [
{
name: 'WEEKLY WRITE ARTICLES',
type: 'pie',
roseType: 'radius',
radius: '50%',
data: data,
animationEasing: 'cubicInOut',
animationDuration: 2600
}
]
});
}
}
}
</script>
then I use this component in a view.
<template>
<pie-chart :chartData="updateData"/>
</template>
<script>
export default {
name: 'Personalinforadm',
components: {
PieChart,
},
data() {
return {
updateData: {
data:[
{ value: 33, name: 'group_a' },
{ value: 17, name: 'group_b' },
{ value: 3, name: 'group_c' },
],
legend:['group_a','group_b','group_c']
}
}
},
created() {
this.updateData = {
data:[
{ value: 3, name: 'group_a' },
{ value: 17, name: 'group_b' },
{ value: 3, name: 'group_c' },
],
legend:['group_a','group_b','group_c']
}
}
}
</script>
however the view doesn't update the PIE chart component with the new values in created methods. why the new values doesn't pass to the PIE component and trigger the watch methods, any ideas what goes wrong with the code?
take a look at https://github.com/ecomfe/vue-echarts or solution below may help you.(if you use version >4.x)
sample.vue
<template>
//...
<v-chart
class="chart mt-7"
:option="botChartData"
:update-options="updateOpts"
/>
//...
</template>
<script>
export default {
data() {
return {
updateOpts: {
notMerge: true,
},
botChartData: {
tooltip: {
trigger: "item",
formatter: "{a} <br/>{b} : {c} ({d}%)",
},
series: [
{
name: "Active Bots",
type: "pie",
center: ["50%", "50%"],
radius: ["75%", "90%"],
itemStyle: {
borderRadius: 8,
},
data: [],
}
],
},
};
},
methods: {
connect() {
this.bots = [
{
value: 0,
name: "a",
},
{
value: 1,
name: "b",
},
{
value: 2,
name: "c",
},
];
this.botChartData.series[0].data = this.bots;
}
},
};
</script>
I called "connect" in "created" you can call it in mounted or on events!
if you need to set your chart as a child component you can easily pass this.botChartData like below
child.vue
<template>
<v-chart
class="chart mt-7"
:option="botData"
:update-options="updateConf"
/>
</template>
<script>
export default {
props: {
botChartData: {
type: Object
},
updateOpts: {
type: Object
}
},
computed: {
botData() {
return this.botChartData
},
updateConf() {
return this.updateOpts
}
}
};
</script>
in parent.vue
<template>
//...
<sample :botChartData="botChartData" :updateOpts="updateOpts" />
//...
</template>
<script>
//...the same as sample.vue js
</script>
By the way if you have multiple charts in one page dont forget notMerge then your charts will reinitialize after switching between them
in a normal way with out translation but i want to translate the two object array and bind into a component
<InfoNews
v-for="infonew in infonews"
:id="infonew.id"
:title="infonew.title"
:content="infonew.content"
/>
data() {
return {
infonews: [
{
id: "01",
title: "what we do",
content:"industke aecimen book. ",
},
{
id: "02",
title: "our mission",
content:"ggdddg",
},
],
};
Make infonews a computed property. The title and content of each should be the translation keys.
export default {
computed: {
infonews() {
return [
{
id: "01",
title: this.$t("what we do"),
content: this.$t("industke aecimen book"),
},
{
id: "02",
title: this.$t("our mission"),
content: this.$t("ggdddg"),
},
]
};
}
}
I have a set of data which I need to filter via pipe. Now, in that data array, some objects have a nested array. Similar to this:
this.testArray = [
{
name: "Ford",
cars: [
{
name: "Figo",
year: "2015"
},
{
name: "Ecosport",
year: "2021"
},
{
name: "Endeavour",
year: "2021"
}
],
location: "USA"
},
{
name: "Suzuki",
location: "Japan"
},
{
name: "Honda",
cars: [
{
name: "Brio",
year: "2015"
},
{
name: "Amaze",
year: "2021"
},
{
name: "CR-V",
year: "2021"
}
],
location: "Japan"
},
{
name: "Hyundai",
cars: [
{
name: "Tucson",
year: "2015"
},
{
name: "Creta",
year: "2021"
},
{
name: "Venuw",
year: "2021"
}
],
location: "South Korea"
},
{
name: "Renault",
cars: [
{
name: "Duster",
year: "2015"
},
{
name: "Scala",
year: "2021"
},
{
name: "Kwid",
year: "2021"
}
],
location: "France"
}
];
Now, the requirement is that when I type a company name it should filter and when I type a car name, the same should happen with the nested array returning only the filtered car name. Eg: If I search for 'Figo', it should return me Ford and then Figo nested inside.
here is my pipe I am using for this:
#Pipe({ name: "carCompSearch" })
export class CarCompSearch implements PipeTransform {
transform(carData: [], searchString: string) {
if (!carData || !searchString) {
return carData;
}
return carData.filter((item: any) => {
return item.name.toLowerCase().includes(searchString.toLowerCase());
});
}
}
I know the pipe is incomplete. Need help in completing this.
and here is the template:
<div *ngFor="let comp of testArray | carCompSearch: searchString">
<h2>{{comp.name}}</h2>
<h5>{{comp.location}}</h5>
<ul>
<li *ngFor="let model of comp.cars">
<span>{{model.name}} - {{model.year}}</span>
</li>
</ul>
</div>
your help is appreciated.
Here is the fork link:
https://codesandbox.io/s/custompipe-forked-5urrl
This may help you out:
#Pipe({ name: "carCompSearch" })
export class CarCompSearch implements PipeTransform {
transform(carData: any[], searchString: string) {
if (!carData || !searchString) {
return carData;
}
const carDataWithNestedFilter = carData.map((item) => {
const newItem = { ...item }; // copy the item to not manipulate the original one
newItem.cars = item.cars?.filter((car) =>
car.name.toLowerCase().includes(searchString.toLowerCase())
);
return newItem;
});
return carDataWithNestedFilter.filter((item) => {
const nameIncludes = item.name
.toLowerCase()
.includes(searchString.toLowerCase());
return item.cars?.length > 0 || nameIncludes;
});
}
}
I'm trying to enable some operations on my grid such as grouping, filtering and sorting, individually they works as shown in the docs but there is no an example of those functionality working together.
By myself I was able to combine sorting and filtering but grouping does not work when i'm adding it as it shown in the docs. look at at my code
<template>
<div>
<Grid :style="{height: '100%'}"
ref="grid"
:data-items="getData"
:resizable="true"
:reorderable="true"
#columnreorder="columnReorder"
:filterable="true"
:filter="filter"
#filterchange="filterChange"
:sortable="true"
:sort= "sort"
#sortchange="sortChangeHandler"
:groupable="true"
:group= "group"
#dataStateChange="dataStateChange"
:columns="columns">
</Grid>
</div>
</template>
<script>
export default {
data() {
return {
items: [],
editID: null,
columns: [
{ field: 'AbsenceEmployeID', filterable:false, editable: false, title: '#'},
{ field: 'Employe', title: 'Employer', cell: DropDownEmployes},
{ field: 'Remarque', title: 'Remarque'},
{ field: 'Type', title: 'Type', cell: DropDownTypes},
{ field: 'CreatedDate', filter:'date', editable: false, editor: 'date', title: 'créé le', format: '{0:d}'},
{ title: 'Actions', filterable:false, cell: CommandCell}
],
filter: {
logic: "and",
filters: []
},
sort: [
{ field: 'CreatedDate', dir: 'desc' }
],
group: [],
gridData: []
}
}
mounted() {
this.loadItems()
},
computed: {
absencesList() {
return this.items.map((item) => Object.assign({ inEdit: item.AbsenceEmployeID === this.editID}, item));
},
getData() {
return orderBy(filterBy(this.absencesList, this.filter), this.sort);
},
...mapState({
absences: state => state.absences.absences
})
}
methods: {
loadItems () {
this.$store.dispatch('absences/getAbsences')
.then(resp => {
this.items = this.absences.map(item => item)
})
},
filterChange: function(ev) {
this.filter = ev.filter;
},
columnReorder: function(options) {
this.columns = options.columns;
},
sortChangeHandler: function(e) {
this.sort = e.sort;
},
// the following is for grouping but not yet used, read more
groupedData: function () {
this.gridData = process(this.getData, {group: this.group});
},
createAppState: function(dataState) {
this.group = dataState.group;
this.groupedData();
},
dataStateChange: function (event) {
this.createAppState(event.data);
},
}
}
</script>
The last three methods are not used yet, so filtering and sorting is working perfectly as of now. then in other to enable grouping I want to replace :data-items="getData" by :data-items="gridData" and run this.groupedData() method after the items are loaded but grouping doesn't work.
I think everything should be handle by the dataStateChange event and process() function but I also tried but without success
If you define the filterchange and sortchange events they are being triggered for filter and sort and you will have to updated data in their handlers. If you rather want to use datastatechage event for all the changes you have to remove the filterchange and sortchange events and the datastatechage event will be triggered instead of them. In this case you will have to update the data in its handler.
You can use the process method of #progress/kendo-data-query by passing the respective parameter each data change that is needed as in the example below:
const result = process(data, {
skip: 10,
take: 20,
group: [{
field: 'category.categoryName',
aggregates: [
{ aggregate: "sum", field: "unitPrice" },
{ aggregate: "sum", field: "unitsInStock" }
]
}],
sort: [{ field: 'productName', dir: 'desc' }],
filter: {
logic: "or",
filters: [
{ field: "discontinued", operator: "eq", value: true },
{ field: "unitPrice", operator: "lt", value: 22 }
]
}
});
Hers is a sample stackblitz example where such example is working correctly - https://stackblitz.com/edit/3ssy1k?file=index.html
You need to implement the groupchange method to handle Grouping
I prefer to use process from #progress/kendo-data-query
The following is a complete example of this
<template>
<Grid :style="{height: height}"
:data-items="gridData"
:skip="skip"
:take="take"
:total="total"
:pageable="pageable"
:page-size="pageSize"
:filterable="true"
:filter="filter"
:groupable="true"
:group="group"
:sortable="true"
:sort="sort"
:columns="columns"
#sortchange="sortChangeHandler"
#pagechange="pageChangeHandler"
#filterchange="filterChangeHandler"
#groupchange="groupChangeHandler"
/>
</template>
<script>
import '#progress/kendo-theme-default/dist/all.css';
import { Grid } from '#progress/kendo-vue-grid';
import { process } from '#progress/kendo-data-query';
const sampleProducts = [
{
'ProductID': 1,
'ProductName': 'Chai',
'UnitPrice': 18,
'Discontinued': false,
},
{
'ProductID': 2,
'ProductName': 'Chang',
'UnitPrice': 19,
'Discontinued': false,
},
{
'ProductID': 3,
'ProductName': 'Aniseed Syrup',
'UnitPrice': 10,
'Discontinued': false,
},
{
'ProductID': 4,
'ProductName': "Chef Anton's Cajun Seasoning",
'UnitPrice': 22,
'Discontinued': false,
},
];
export default {
components: {
Grid,
},
data () {
return {
gridData: sampleProducts,
filter: {
logic: 'and',
filters: [],
},
skip: 0,
take: 10,
pageSize: 5,
pageable: {
buttonCount: 5,
info: true,
type: 'numeric',
pageSizes: true,
previousNext: true,
},
sort: [],
group: [],
columns: [
{ field: 'ProductID', filterable: false, title: 'Product ID', width: '130px' },
{ field: 'ProductName', title: 'Product Name' },
{ field: 'UnitPrice', filter: 'numeric', title: 'Unit Price' },
{ field: 'Discontinued', filter: 'boolean', title: 'Discontinued' },
],
};
},
computed: {
total () {
return this.gridData ? this.gridData.length : 0;
},
},
mounted () {
this.getData();
},
methods: {
getData: function () {
this.gridData = process(sampleProducts,
{
skip: this.skip,
take: this.take,
group: this.group,
sort: this.sort,
filter: this.filter,
});
},
// ------------------Sorting------------------
sortChangeHandler: function (event) {
this.sort = event.sort;
this.getData();
},
// ------------------Paging------------------
pageChangeHandler: function (event) {
this.skip = event.page.skip;
this.take = event.page.take;
this.getData();
},
// ------------------Filter------------------
filterChangeHandler: function (event) {
this.filter = event.filter;
this.getData();
},
// ------------------Grouping------------------
groupChangeHandler: function (event) {
this.group = event.group;
this.getData();
},
},
};
</script>
I'm trying to use apollo-client in my react-native app but for some reason I can only get results from queries when I use certain fields.
Here's my first query :
`query RootQueryType($page: Int!) {
events(page: $page) {
title
}
}`
Working perfectly in RN and GraphiQL but as soon as I add or use an other field than title I don't get any result from the query in RN. It's working perfectly in GraphiQL and there's no error at all.
For example :
`query RootQueryType($page: Int!) {
events(page: $page) {
description
}
}`
Here's my event type :
const EventType = new GraphQLObjectType({
name: 'EventType',
fields: () => ({
id: { type: GraphQLID },
title: { type: GraphQLString },
category: { type: GraphQLString },
description: { type: GraphQLString },
terminated: { type: GraphQLBoolean },
coverUrl: { type: GraphQLString },
startDate: { type: GraphQLString },
endDate: { type: GraphQLString },
price: { type: GraphQLFloat },
website: { type: GraphQLString },
ticketsUrl: { type: GraphQLString },
geometry: { type: GraphQLString },
participantsCount: { type: GraphQLInt },
participants: {
type: new GraphQLList(UserType),
resolve(parentValue) {
return Event.findParticipants(parentValue.id);
}
}
})
});