Vue property definition warning even though it is defined on the instance - javascript

Edit - I have setup a repo on github with the erraneous code here if anyone wants to pull this down and see the error for themselves: https://github.com/andrewjrhill/what-the-instance-grid. You can run npm run serve to kick off the webserver.
I am running into an issue where my Vue is throwing the following errors:
[Vue warn]: Property or method "columns" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
[Vue warn]: Property or method "items" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
This is a pretty common issue with Vue apps and is usually the result of a property not being defined on a Vue data object. Unfortunatley in this case I have indeed added columns and itemsto the new Vue call. Any ideas why I am getting this error? It looks like data isn't available at all to the template.
This project was generated by the latest Vue-CLI and is using the runtimeCompiler: true flag in a vue.config.js file if that makes any difference.
The .vue file in question:
<template>
<div id="vueapp" class="vue-app">
<Grid :columns="columns" :data-items="items" :style="{ height: '280px' }"></Grid>
</div>
</template>
<script>
import Vue from "vue";
import { Grid } from "#progress/kendo-vue-grid";
Vue.component("Grid", Grid);
new Vue({
el: "#vueapp",
data: function() {
return {
items: [],
columns: [
{ field: "ProductID" },
{ field: "ProductName", title: "Product Name" },
{ field: "UnitPrice", title: "Unit Price" }
]
};
},
methods: {
createRandomData(count) {
const productNames = [
"Chai",
"Chang",
"Syrup",
"Apple",
"Orange",
"Banana",
"Lemon",
"Pineapple",
"Tea",
"Milk"
];
const unitPrices = [12.5, 10.1, 5.3, 7, 22.53, 16.22, 20, 50, 100, 120];
return Array(count)
.fill({})
.map((_, idx) => ({
ProductID: idx + 1,
ProductName:
productNames[Math.floor(Math.random() * productNames.length)],
UnitPrice: unitPrices[Math.floor(Math.random() * unitPrices.length)]
}));
}
},
mounted() {
this.items = this.createRandomData(50);
}
});
export default {
name: "App",
components: {
Grid
}
};
</script>

Don't reinstantiate Vue inside the App.vue component.
Fix like this (files from your repo):
main.js:
import App from './App.vue'
import Vue from 'vue'
import { Grid } from "#progress/kendo-vue-grid";
Vue.component("Grid", Grid);
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#vueapp')
App.vue:
<template>
<div id="vueapp" class="vue-app">
<Grid :columns="columns" :data-items="items" :style="{ height: '280px' }"></Grid>
</div>
</template>
<script>
export default {
name: "App",
data: function() {
return {
items: [],
columns: [
{ field: "ProductID" },
{ field: "ProductName", title: "Product Name" },
{ field: "UnitPrice", title: "Unit Price" }
]
};
},
methods: {
createRandomData(count) {
// your code
}
},
mounted() {
this.items = this.createRandomData(50);
}
};
</script>

Related

Why can't I resize the columns of Fluent UI's DetailsList component?

I created a react app with 'npx create-react-app'. I installed the npm package by running 'npm i #fluentui/react'. I implemented the DetailsList component of Fluent UI in my App.js:
import "./App.css";
import { DetailsList } from "#fluentui/react";
function App() {
const columns = [
{
key: "column1",
name: "Name",
fieldName: "name",
minWidth: 100,
maxWidth: 200,
isResizable: true,
},
{
key: "column2",
name: "Value",
fieldName: "value",
minWidth: 100,
maxWidth: 200,
isResizable: true,
},
];
const items = [
{ key: 1, name: "good", value: 1 },
{ key: 2, name: "bad", value: 2 },
];
return (
<div className="App">
<DetailsList items={items} columns={columns} setKey="set" />
</div>
);
}
export default App;
I can see the list properly but I can't resize the columns. Even though I set 'isResizable: true' for every column. Why? How can I make them resizable. Btw: unlike the Fluent UI documentation, I want to use functional components (I hope this isn't the problem).
I updated office-ui-fabric-react "7.202.0" from "7.156.0".
Imported IColumn from "#pnp/spfx-controls-react/node_modules/office-ui-fabric-react" instead of just "office-ui-fabric-react"
this worked for me.

How to autofocus Quill Editor in Vue.js?

I'm using quill with vue 3 and can't find a way to autofocus the editor input field in their docs.
I've tried targeting parent elements with:
document.getElementById(...).focus()
which did nothing. This is how I've implemented quill, text-editor.vue:
<template>
<div id="text-editor" class="text-editor">
<quill-editor :modules="modules" :toolbar="toolbar"/>
</div>
</template>
<script setup>
import BlotFormatter from 'quill-blot-formatter'
const modules = {
module: BlotFormatter,
}
const toolbar = [
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'size': ['small', false, 'large', 'huge'] }],
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ 'align': [] }],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'color': [] }, { 'background': [] }],
[{ 'font': [] }],
['link', 'image', 'video'],
['clean']
];
</script>
and import it in component.vue:
<template>
<div id="component">
<text-editor/>
</div>
</template>
<script setup>
import textEditor from './text-editor'
</script>
Any idea how to autofocus quill?
I found the solution. Just use the #onReady event. As simple as this:
<QuillEditor
theme="snow"
#ready="onReady"
/>
Then add the method:
methods: {
onReady(editor) {
editor.focus();
},
},
You can access the quill instance with getQuill() API and then use quill.focus() to focus the quill editor, here is an example:
<template>
<QuillEditor
ref="quillEditor"
theme="snow"
:options="options"
#ready="onQuillReady"
/>
</template>
<script setup>
import { ref } from "vue";
import { QuillEditor } from "#vueup/vue-quill";
import "#vueup/vue-quill/dist/vue-quill.snow.css";
const quillEditor = ref(); // editor ref
const options = {
// ... options for quill editor ...
}
function onQuillReady() {
// focus editor when it is ready
quillEditor.value.getQuill().focus();
}
</script>
Ref: https://vueup.github.io/vue-quill/api/methods.html#getquill

Vue Array prop default value doesn't work

I do the same as in the following Vue 2 - How to set default type of array in props
Vue.component("Test-Attribute", {
props: {
attributes: {
type: Array,
required: false,
// Object or array defaults must be returned from
// a factory function
default: function () {
return [
{attributeName: 'One', multiselect: 0},
{attributeName: 'Two', multiselect: 1},
{attributeName: 'Three', multiselect: 0},
{attributeName: 'Four', multiselect: 1},
]
}
}
},
template: `
<div>
<component
v-for="(attribute,index) in attributes"
:key="index"
:name="attribute.attributeName"
:is="getAttributeType(attribute)"
>
{{ attribute.attributeName + ':' }}
</component>
</div>
`,
created() {
console.log(this.attributes)
},
methods: {
getAttributeType: function (attribute) {
return parseInt(attribute.multiselect) === 1 ? 'MultiAttribute' : 'SingleAttribute'
}
}
});
Updated the original question with the full component code, I I pass down a prop the component is rendered as expected
The syntax is OK, I passed down an empty array and props default value is used only if the value is null or undefined.

Dynamic lookup from React's state in material-table

I'm using the material-table component, which I fill with dynamic data coming from Redux (an array of objects), but then I do other things with that data inside my component's state. To create column dropdown filters, there's an element inside each column's array of options, lookup, that receives an object and creates the dropdown based on it's values.
I am extracting some items from my data and putting them inside an element in my component's state. This is an object, the same kind that lookup receives. The thing is that the component shows an empty dropdown, as if the object was empty, but it's not. I'm logging it in into the console and the object is filled with the data I need.
I initially thought it was a render problem, that the object is empty at the beggining, and then it's filled with data, but the component renders every time.(Yeah, React is reactive).
This is only the code needed to help me solve this problem:
Table component
import React, { Component } from "react";
import MaterialTable from "material-table";
class CustomTable extends Component {
state = {
column1: "",
column2: "",
column3: "",
column1FilterList: {}
columns: [
{
title: "Column1",
field: "column1",
editable: "onAdd",
filtering: true,
lookup: { ...this.column1FilterList }
},
{
title: "Column2",
field: "column2",
editable: "onAdd",
filtering: true,
},
{
title: "Column3",
field: "column3",
editable: "onAdd",
filtering: true
}
]
};
componentDidMount() {
this.props.fetchValues()
this.props.fetchApplications()
this.filterColumn1ExistingKeys()
}
filterColumn1ExistingKeys = () => {
return this.props.elements.map(element => {
return this.setState(prevState => ({
column1FilterList: {
...prevState.column1FilterList,
[element.name]: element.name
}
}))
})
}
render() {
return (
<div>
<MaterialTable
options={{
search: false,
actionsColumnIndex: 4,
filtering: true
}}
title="Search by"
columns={this.state.columns}
data={this.state.data}
/>
</div>
);
}
}
export default CustomTable;
The problem is how you save that data. You create a new object in the constructor with { ...this.column1FilterList }. This will create a new object which will act as the lookup object, which is filled with the initial data of column1FilterList (empty). Updating the column1FilterList later does not change that lookup object, because it is disconnected (new object). You have to update the lookup within the columns as well like this:
const filterColumn1ExistingKeys = () => {
const column1FilterList = this.state.column1FilterList;
this.props.elements.forEach(element => column1FilterList[element.name] = element.name)
this.setState({
column1FilterList,
columns: [{
title: "Column1",
field: "column1",
editable: "onAdd",
filtering: true,
lookup: { ...column1FilterList }
},
{
title: "Column2",
field: "column2",
editable: "onAdd",
filtering: true,
},
{
title: "Column3",
field: "column3",
editable: "onAdd",
filtering: true
}
]
})
}
Hope this helps. Let me know, if that works for you. If you have any questions, let me know. Happy coding.

KoGrid not working in Durandal JS framework

How can i bind a koGrid in durandal JS view page.The code given below not working.
view(html)
<div id="functiontable" class="form-actions">
<div style="height: 200px" data-bind="koGrid: {
data: items, columnDefs: [{ field: 'id', width: 140 },
{ field: 'name', width: 100 },
{ field: 'price', width: 150 }
],
autogenerateColumns: false,
isMultiSelect: false,
enableSorting: true
}"></div>
</div>
viewmodel(js)
define([ 'repositories/customerRepository', 'plugins/router', 'plugins/http', 'durandal/app', 'knockout'], function (customerRepository, router, http, app, ko) {
var items = ko.observableArray([
{ id: 1, name: "abc", price: "asds" },
{id:1,name:"abc",price:"asds"},
]);
return {
router: router,
items:items,
activate: function () {
},
attached: function (view) {
},
};});
If I inspect the element from browser the grid loads its value.I don't know how to clear the issue.Can anyone help me?
Items needs to actually be returned in order to be used by your view, so:
items: ko.observableArray([
{ id: 1, name: "abc", price: "asds" },
{id:1,name:"abc",price:"asds"}
]),
activate: function () {
}
Tip
When doing this stuff, use a client-side debugger such as the Chrome web tools (F12 in Chrome) - that'll highlight that "items" cannot be found.

Categories

Resources