How to Set Selected Children while Loading vuetify Treeview? - vuetify.js

I am working with v-Treeview. I want to set already selected children while loading this tree view. To do this, I added items in array and used this array in v-model. But It's not working. I have following implementations:
<template>
<v-container>
<v-treeview
:items="checklist"
selectable
return-object
dense
hoverable
:v-model="selectedItemList"
/>
</v-container>
</template>
<script>
export default {
name: 'WTreeView',
props: {
// Checklist of the selected card
checklist: {
type: Array,
required: true,
},
},
data() {
return {
selectedItemList: [],
};
},
created() {
this.selectedItemList.push(this.checklist[0]);
},
};
</script>
For "checklist" I have data in the following format:
Now what is the best way to set already selected children while loading v-Treeview? Thank You.

When the vue is created, the data hasn't been filled into the controllers and neither the page is rendered.
You can consider setting the selected items in the mounted

I have been working on a similar issue for hours and finally figured out how to get it work.
First of all, v-treeview needs a separate array of ids to keep the track of selected items.
you should bind it to the value property.
Second, the timing you change the value property is critical. v-model would not load the initial values so you have to update the values after you render the page. In your code above, you set the selectedItemList in created(). But it is executed before the page is rendered. You should put it into mounted() instead.

I don't think you can achieve this "out of the box".
I recommend using the "label" slot to add your own v-checkbox and bind the v-model to the selected property on your check list item.
Something like:
<v-treeview :items="checklist">
<template v-slot:label="props">
<div class="treeCheckBox">
<v-checkbox class="treeCheckBox"
v-model="props.item.selected"
:label="props.item.name">
</v-checkbox>
</div>
</template>
</v-treeview>
Then all you need to do is ensure the "selected" property is set appropriately against the check list items when the data is bound to the tree view.
For more info on the using the named slot, see https://vuetifyjs.com/en/components/treeview and https://v2.vuejs.org/v2/guide/components-slots.html
In version 1.5x of veutify you may encounter spacing issues. I was able to fix this by applying the following styles to my check box and outer div:
.treeCheckBox{
margin-top: 0px;
max-height: 30px;
}

Related

Vuetify3 v-combobox and cypress: How to identify list items?

I am in the process of migrating to vuetify3, and I'm using cypress (the cypress studio) for testing.
The <v-combobox> gives me a dropdown with items, but these are not easily referencable with css selectors. Cypress studio generates stuff like
cy.get('.v-overlay__content > .v-list > :nth-child(2) > .v-list-item__content > .v-list-item-title').click();
... which isn't readable for a human and will break if the dropdown list gets modified (for example, prepend a list item).
The best solution I came up with yet would be to give each list item a data-cy attribute; but how to do that properly? It seems to me that vuetify3 docs are still sparse on how to use the item slot (cf. https://next.vuetifyjs.com/en/components/combobox/); its workings seem to differ from vuetify2. By using the item slot like,
<v-combobox>
<template #item="scope">
myListItem
</template>
</v-combobox>
... the list items are not clickable any more.
Codesandbox: https://codesandbox.io/s/vuetify3-v-combobox-and-cypress-how-to-identify-list-items-gzfs71?file=/src/App.vue
EDIT Of course I could write the Cypress test code myself. But my premise is to use Cypress Studio, which CAN generate meaningful CSS selectors if possible, i. e. if there are id or data-cy attributes in the HTML code. But vuetify does not generate such. So I ask, how can I attach data-cy attributes to list items?
I think your selector is a bit more complex than needed
you can simplify to just the relevant elements
// get based on value
cy.get(".v-overlay-container .v-list-item").contains("Programming").click();
// get based on order (force: true is required if the combo box is still animating)
cy.get(".v-overlay-container .v-list-item").eq(2).click({ force: true });
example used
<template>
Click this combobox:
<v-combobox :items="items" id="combo" />
</template>
<script>
import { VCombobox } from "vuetify/components";
export default {
name: "App",
data() {
return {
items: ["Programming", "Design", "Vue", "Vuetify"],
};
},
components: { VCombobox },
};
</script>
test
describe("💩💩", () => {
beforeEach(() => {
cy.visit("http://10.0.0.248:8080/");
});
it("select with content", () => {
cy.get("#combo").click();
cy.get(".v-overlay-container .v-list-item").contains("Programming").click();
cy.get("#combo").should("have.value", "Programming");
});
it("select with order", () => {
cy.get("#combo").click();
cy.get(".v-overlay-container .v-list-item").eq(2).click({ force: true });
cy.get("#combo").should("have.value", "Vue");
});
});

How to add an external jQuery plugin to the list view on Odoo?

I am using Odoo 10e. I want to integrate a jquery plugin into my module.
I want to integrate the jQuery plugin jquery-resizable-columns. It simple helps user to resize columns of table on the fly and I want to apply this on a specific model's list view
Which method should I extend in order to add the plugin?
I think you should extend (maybe include) some widget in the web module. If you go to the file /addons/web/static/src/js/view_list.js, you can see the widget that renders the table:
instance.web.ListView = instance.web.View.extend( /** #lends instance.web.ListView# */ {
_template: 'ListView',
display_name: _lt('List'),
defaults: {
// records can be selected one by one
'selectable': true,
// list rows can be deleted
'deletable': false,
// whether the column headers should be displayed
'header': true,
// display addition button, with that label
'addable': _lt("Create"),
// whether the list view can be sorted, note that once a view has been
// sorted it can not be reordered anymore
'sortable': true,
// whether the view rows can be reordered (via vertical drag & drop)
'reorderable': true,
'action_buttons': true,
//whether the editable property of the view has to be disabled
'disable_editable_mode': false,
},
view_type: 'tree',
events: {
'click thead th.oe_sortable[data-id]': 'sort_by_column'
},
// [...]
sort_by_column: function (e) {
e.stopPropagation();
var $column = $(e.currentTarget);
var col_name = $column.data('id');
var field = this.fields_view.fields[col_name];
// test whether the field is sortable
if (field && !field.sortable) {
return false;
}
this.dataset.sort(col_name);
if($column.hasClass("sortdown") || $column.hasClass("sortup")) {
$column.toggleClass("sortup sortdown");
} else {
$column.addClass("sortdown");
}
$column.siblings('.oe_sortable').removeClass("sortup sortdown");
this.reload_content();
},
As you can see there is an event declared as sort_by_column, so you would have to add the plugin you want in a similar way.
And if you have any doubts inheriting and modifying widgets you can go to the Odoo Documentation
And if you are using the version 10 you can check how it is built here
/addons/web/static/src/js/views/list_view.js
In .js file you have to first extend particular list view's js. After that give your custom model name in that .js file and run that.
In your case, You need.
Created a new module or modify already custom module
Create file.js and file.xml.
In the file xml you must write this
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/module_name/static/src/css/css_file.css"/>
<script type="text/javascript" src="/module_name/static/src/js/js_file.js"></script>
</xpath>
</template>
</odoo>
And after you needing extent the list_view.js of Odoo to integrate your plugin.

polymer iron-list only loading 20 items

I have an a test array that I am retrieving from iron-ajax with around 1000 items. I set that return array to the people property of my custom polymer element. Iron-list is displaying the first 20 results, but when i scroll down the rest of the results are not being loaded.
<link rel="import" href="/bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="/bower_components/iron-list/iron-list.html">
<link rel="import" href="/bower_components/iron-flex-layout/classes/iron-flex-layout.html">
<dom-module id="people-list">
<template>
<iron-list items="[[people]]" as="item" class="flex">
<template>
<div style="background-color:white; min-height:50px;">[[item.city]]</div>
</template>
</iron-list>
<iron-ajax
auto
id="ajaxPeopleList"
method="POST"
url="/people/list"
handle-as="json"
last-response="{{people}}">
</iron-ajax>
</template>
<script>
Polymer({
is: 'people-list',
properties: {
people: {
type: Array
}
}
});
</script>
</dom-module>
I think it may have to do with the height of the screen/iron-list element, but I am stuck and not sure how to proceed.
I can get it load all items if I set the height of the iron-list elements in pixels. But I just want it to fit on the screen. The docs make it look like you can use the iron-flex layout and use the class flex, which is what I tried to do in my sample code, but it has no effect.
This is because nothing is firing the iron-resize event to tell the iron-list to redraw the items. According to the docs:
Resizing
iron-list lays out the items when it recives a notification via the iron-resize event. This event is fired by any element that implements IronResizableBehavior.
By default, elements such as iron-pages, paper-tabs or paper-dialog will trigger this event automatically. If you hide the list manually (e.g. you use display: none) you might want to implement IronResizableBehavior or fire this event manually right after the list became visible again. e.g.
document.querySelector('iron-list').fire('iron-resize');
I've added the following to your code (which is probably a bit of a hack) and got it working:
ready: function () {
document.addEventListener("scroll", function () {
// fire iron-resize event to trigger redraw of iron-list
document.querySelector('iron-list').fire('iron-resize');
});
}
Ben Thomas is right. You're getting the json elements but it's not displayed because the iron-list needs to be redrawn. Since i had the same problem, i went to google polymers website and found THIS code example.
In short for your example:
<script>
// Only execute after DOM and imports (in our case the json file) has been loaded
HTMLImports.whenReady(function() {
Polymer({
is: 'people-list',
properties: {
people: {
type: Array
}
},
attached: function() {
// Use the top-level document element as scrolltarget
this.$.list.scrollTarget = this.ownerDocument.documentElement;
}
});
});

drop-area element not hiding with DND module and FineUploaderBasic

I've got everything working well except the drop area element doesn't hide after moving back off the page.
For example, if I drag something to the page, the drop area element shows, but then if I decide not to drop, it stays visible instead of hiding. It looks like in the demos on the site, it should hide again.
I've been studying this page: http://docs.fineuploader.com/branch/master/integrating/options/fineuploader.html#draganddrop-option-properties
There doesn't seem to be a callback for when there is no longer a file about to be dropped in the browser window. My code looks just like the examples, but has my own element id and class names, both of which work.
Any ideas?
Update - here is some code:
<div id="file-upload-well" class="well text-center">
<div id="file-upload-drop-area" style="display:none;">Drop files here</div>
Upload Files
</div>
and here is the DND js:
var dragAndDropModule = new qq.DragAndDrop({
dropZoneElements: [document.getElementById('file-upload-drop-area')],
classes: {
dropActive: "dropActive"
},
callbacks: {
processingDroppedFiles: function () {
$('#file-upload-drop-area').hide();
},
processingDroppedFilesComplete: function(files) {
uploader.addFiles(files);
}
}
});
The issue was setting the hideDropZonesBeforeEnter is set to false by default and needed to be set to true.
Both the variable name and the help documentation make it seem it will only show the drop zone when a file is directly over it, but instead it hides and shows the dropdown when a file is over a compliant browser.

jQuery - How to call/bind jquery events for elements added by ajax?

I'm working on an implementation of the jQuery plugin Tag-it! with a product entry form for assigning attributes to products of different type (laptops, tv's, gadgets etc).
The concept is the following:
When adding a new product, first, the user selects the product category from a dropdown for the product being added and a jQuery .change() event is triggered making an ajax call to get all the attributes that are related to that category. For example, if Im adding a TV i want my ajax call to populate 3 inputs for inches, panel type, hdmi whereas, if i'm adding a laptop I want those inputs to be cpu, ram, hdd, screen etc. Tag-it! works with a list of words (in my case, attributes) and an input field for choosing the set of words.
In my case, for each type of attributes I want to populate a separate input field and assign/bind it to/apply tagit plugin (sorry, I dont know how else to explain it).
Javascript:
<script src="../js/tag-it.js" type="text/javascript" charset="utf-8"></script>
<script>
$(function(){
// Sample1: var sampleTags1 = ["red", "green", "blue"];
// Sample2: var sampleTags2 = ["lcd", "plasma", "tft"];
var sampleTags1 = [<?=createTags('name', 'tags', 1)?>];
// createTags($name, $tags, $id) is a PHP function that returnss a list of tags for a given attribute
// Question 1: how do I place this here after a new input is added to the DOM?
$('#myTags').tagit();
//Question 2: for each input added to the DOM I need also to add this block in the javascript:
$('#allowSpacesTags1').tagit({itemName: 'item1', fieldName: 'tags1',
availableTags: sampleTags1, allowSpaces: true
});
$('#removeConfirmationTags').tagit({
availableTags: sampleTags,
removeConfirmation: true
});
});
$(document).ready(function() {
$('#cat_id').change(function(){
$.post('../includes/ajax.php', {
cat_id : $(this).find("option:selected").attr('value')}, function(data) {
$("#tagholder").html(data);
});
});
});
</script>
Ajax returns the following for each call:
<ul id="allowSpacesTags'.$row['ctid'].'"></ul> // $row['ctid'] is the ID for that attribute
which represents the input field for entering the tags/attributes.
Before there's any misunderstanding, I'm not asking how to do this in PHP.
My question is about the way I can dynamically add a var like sampleTags1 and also call the tagit() for each new input that is added to the DOM by ajax. I'll try to give any required information if my question isn't clear enough.
Please look at the questions in the code comments. Thanks!
http://api.jquery.com/live/
with .live( events, handler(eventObject) )
you don't need to attach or re-attach events when content is added dynamically
EDIT
i've just notticed that live is deprecated, instead you should use
.on()
http://api.jquery.com/on/

Resources