I'm trying to add a context menu to my SyncFusion TreeGrid, but nothing seems to happen.
This is what my file looks like:
<template>
<ej2-treegrid
:dataSource="tabla"
:contextMenuItems="contextMenuItems"
rowHeight="20px"
><e-columns>
<e-column field="nombre" headerText="Nombre"></e-column>
<e-column field="cantidad" headerText="Cantidad"></e-column>
<e-column field="vu" headerText="Valor Unitario" format="C"></e-column>
<e-column field="precio" headerText="Precio" format="C"></e-column>
</e-columns>
</ej2-treegrid>
</template>
<script setup>
import { ref, reactive, provide } from "vue";
import { TreeGridComponent as ej2Treegrid,
ColumnsDirective as eColumns,
ColumnDirective as eColumn,
ContextMenu,
} from '#syncfusion/ej2-vue-treegrid';
provide("treegrid", [ContextMenu]);
const contextMenuItems = ["Cancel"];
const tabla = reactive([{id: 1, nombre: "", cantidad: 2, vu: 2, precio: 2}]);
</script>
I'm not sure what I'm doing wrong. Maybe is the provide part? The documentation seems to be for vue2.
When I right click on the grid, the default context menu appears. I've had similar problems with editting.
We suspect that the context menu module is not injected properly. Based on your shared code example, we checked, and the provide part returns an error. So, we suggest you follow the code example below.
Your code:
provide("treegrid", [ContextMenu]);
Modified code:
provide: {
treegrid: [Page, ContextMenu, Edit,],
}
And we have prepared a simple Vue3 sample with context menu and editing. Please refer to the below sample:
https://www.syncfusion.com/downloads/support/directtrac/general/ze/Vue_3_context_menu-200508808
Related
I was able to set the initial value of the content from the editor with the value of a ref, but it doesn't update the content when the value of the ref changes.
Would anyone have an idea how to do it?
<editor-content
:editor="editor"
v-model:content="
/>
<script setup>
import { ref } from 'vue'
import { useEditor, EditorContent } from '#tiptap/vue-3'
import StarterKit from '#tiptap/starter-kit'
const generatedText = ref('<p>Hello!</p>')
/* editor */
const editor = useEditor({
content: generatedText.value,
extensions: [
StarterKit,
],
onUpdate: ({editor}) => {
generatedText.value = editor.getHTML()
}
})
</script>
Sorry if the question is too silly, I couldn't find an answer in the documentation.
Thank you for your help!
How will the generatedText be generated? Through tiptap?
The v-model of tiptap is the editor.content value. You could give it an initial state but if you want to change the editor.content after some interaction with the wysiwyg (like onFocus) you could use: setContent
Or maybe this helps:
Listening for changes
In the simplified example below I demonstrate my problem:
I have a for-loop that asynchronously updates myItems.
I want to be able and update accordingly selectableItems by using this.$el.querySelector('selectable-item').
<template>
<div>
<p>selectableItems: {{selectableItems}}</p>
<div v-for="item in myItems" class="selectable-item">item</div>
</div>
</template>
<script>
export default {
name: 'MyComponent',
data() {
return {
myItems: [],
selectableItems: [],
}
},
created(){
// Populate myItems with a delay
self = this
setTimeout(function() {
self.myItems = [1, 2, 3]
}, 1000);
},
mounted(){
// Fetch some of myItems based on a class
this.selectableItems = this.$el.querySelectorAll('.selectable-item')
},
}
</script>
<style scoped lang="scss">
</style>
I've tried many different things I've found online; TickNext, computed, updated, etc. I think I'm doing something fundamentally wrong. But it is important for my case to be able and select DOM elements by a class.
Any help is deeply appreciated.
Updated: More context
Some people asked me for the bigger picture so I give a bit more info here.
Currently I have a big Vue component where the user is able to select elements. I am trying to factor out all this user interaction into a mixin so I can re-use it in other places of my code.
To make re-usability easy I need to be able and simply add a class selectable to any HTML tag in the template. That's the interface and then the mixin does all the magic and populates selectedElements depending on user interaction.
That's why it is important to avoid refs, etc. since then too much logic leaks everywhere and beats the purpose of making the mixin re-usable. Unless I'm missing something.
OK, after trying many different things I've managed to solve this by using a non-reactive intermediate variable. This means that I can't use the variable in a template but that is fine.
export default {
..
// NOT reactive so you can't just use it in your templates.
_selectableItems: [],
updated(){
self._selectableItems = self.$el.querySelectorAll('.selectable-item')
},
..
}
I'll try to be short but clear.
I downloaded a template of Vuejs for admin (from here), but I am having troubles modifying it. I created one new component but I can't use it because is not being recognized. The console error says:
Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I don't know why is this happening because I am importing the component as every other one. Look the script code in the father component.
import LTable from 'src/components/UIComponents/Tables/Table.vue'
import ETable from 'src/components/UIComponents/Tables/EditableTable.vue' //THIS IS MY NEW COMPONENT
import Card from 'src/components/UIComponents/Cards/Card.vue'
const tableColumns = [//some data]
const tableData = [//some data]
export default {
components: {
LTable,
ETable, //THIS IS MY NEW COMPONENT
Card
},
data () {
return {
//some data
}
},
//some methods
}
Of course the name tag in my new component is 'edit-table'.
There is happening other strange issue: when I change the name value in the component imported as 'LTable' it seems not to matter because everything keeps working good.
Please, any help is appreciated it.
In my Vue 2 application I have a big object that is passed from the root component down several levels to some child components as a prop. When I change some property of the object the child components should update and rerender. In some cases they do, in other cases they don't. I need some help spotting why it does not work.
Here is a child component, which does not update:
<template>
<div class="upgradeBar">
{{level}}
<div
v-for="lvlNum in maxLevel + 1"
class="level"
v-bind:class="{reached: isLevelReached(lvlNum - 1)}"
></div>
<button
class="btnUpgrade"
#click="onLevelUp()"
v-if="!isLevelReached(maxLevel)"
>
+
</button>
</div>
</template>
<script lang="ts">
import {Component, Prop, Vue} from 'vue-property-decorator';
import Upgradable from "../../../models/Upgradable";
#Component()
export default class UpgradeBar extends Vue {
name: 'UpgradeBar';
#Prop() entity: Upgradable;
get level(): number {
return this.entity.level;
}
get maxLevel(): number {
return this.entity.MAX_LEVEL;
}
onLevelUp() {
this.entity.levelUp();
}
isLevelReached(level: number): Boolean {
return this.entity.level >= level;
}
}
</script>
The component is called like this:
<UpgradeBar :entity="entity" />
All the code works. When I click the btnUpgrade button entity.level is indeed changed, but I need to close and reopen the component to see the changes. Also the browser dev tool does not show the change instantly. I need to click on the component to refresh the values in the debugger.
EDIT:
The entity class looks basicly like this (excerpt):
class Entity {
name: string = 'some name';
level: number = 1;
}
I searched deeper and it seems to boils down to this: Some properties of the object are reactive (they have getters / setters created by vue) and some don't. entity.name has a setter, so changing it updates the component. entity.level does not. Here's the question: Why are they treated differently? Here is a log:
Can't tell for sure without seeing the code for entity.levelUp, but it seems like a reactivity issue, that may be solved by using Vue.$set inside that function.
You can confirm this being the case by adding this.$forceUpdate(); after this.entity.levelUp();
update
this._level = this._level + 1;
can be changed to
Vue.$set(this, _level, this._level + 1);
You will need to import Vue in that component/file to access the $set function
You don't show (or I can't find) the code that changes the object, but are you using $set() or Vue.set() instead of simply changing the object's properties directly? Changing a property directly generally doesn't work because of reactivity limitations
Edited to add:
I see now. I think you want something like:
this.$set(this, '_level', this._level + 1);
I am using Aurelia's Custom Elements to repeat over a set of entries. Here is the sample gist: https://gist.run/?id=38aee854447122f021bc05e1e0de25ae
Now, I need to access the deleteEntry(entry) method when clicked on the button defined in custom element. I tried using $parent.deleteEntry(entry) but it's not working.
Saw this issue, but it's more than an year old and I am wondering if there is a cleaner way to achieve this now.
Why not use the call binding to accomplish this?
Here's an example: https://gist.run?id=3cc553ea3bd7ed1862d87d8dbe4f5f84
app.html
<template>
<require from="./entry"></require>
<h2 class='text-center'>Journal Entries</h2>
<div>
<entry repeat.for='entry of entries' entry.bind='entry' delete-function.call="deleteEntry(entry)"></entry>
</div>
</template>
app.js
export class App {
entries = [{
'date': 'Jan 1',
'note': 'Hello World'
}, {
'date': 'Jan 2',
'note': 'Good Morning'
}];
deleteEntry(entry) {
console.log("Deleting entry");
console.log(entry);
const index = this.entries.indexOf(entry);
this.entries.splice(index, 1);
}
}
entry.html
<template>
<div>${entry.date} <button click.trigger='delete()'>X</button></div>
<div>${entry.note}</div>
</template>
entry.js
import {bindable} from 'aurelia-framework';
export class EntryCustomElement {
#bindable entry;
#bindable deleteFunction;
delete() {
this.deleteFunction();
}
}
Obviously in a real implementation, you'll need to make sure that what is bound to deleteFunction is actually a function before trying to call it.
Using bind life cycle event you can get parent View modal in Aurelia.
bind(bindingContext, overrideContext) {
this.parent = bindingContext;
}
Now you can access all the variables and methods from parent view to your view.
Like below code in child view
this.parent.parentmethod();