Vue optimization for large dropdowns on list of items - vue.js

I am experiencing some performance issues in Vue after migrating from an old angularjs app.
The page displays a list of available reports with a settings button alongside each report.
Likewise each report has among other things a property called worksheet which indicates the name of the worksheet driving this report.
So for example something like this
<div class="list" v-for="(report,repidx) in filteredReports" v-show="hideDemo.indexOf(report.Name) == -1">
<h2>{{report.Name}}</h2><button #click="report.showsettings=true">Settings</button>
<div v-show="report.showsettings">
<select name="worksheet" v-model="report.worksheet">
<option v-for="worksheet in allworksheets">{{worksheet.Name}}</option>
</select>
</div>
</div>
When clicking on the settings button a dropdown list is exposed which indicates all the available worksheets that could be assigned to the selected report
"allworksheets" is an array of objects which might contain a 1000 worksheets.
Having it populated on the DOM (using v-for) for each report in the list does not seem efficient and causes tremendous performance issues on page loading and also during operations eg clicking on Settings button. (Surprisingly this worked perfectly fine in angularjs).
I tried switching to using a computed property but that also didnt help.
It gets even more complicated because the angular approach also had an additional option group which displayed SIMILAR worksheets to the currently selected one. For eg something like this
<select name="worksheet" v-model="report.worksheet">
<optgroup label="similarworksheets">
<option v-for="sm in similarworksheets(report.worksheet)">{{sm.Name}}</option>
</optgroup>
<optgroup label="allworksheets">
<option v-for="worksheet in allworksheets">{{worksheet.Name}}</option>
</optgroup>
</select>
In this case "similarworksheets" is a method that accepts the report.worksheet as a parameter and returns a filtered version of allworksheets, showing only SIMILAR worksheets. This obviously makes performance even worse!
Can someone suggest a better way to approach this given the fact that I need to stick to this structure - more or less - ie a dropdown list available for each selected report.
Thanks

Related

How to disable the select element in Materialize CSS with VUE?

Goodnight.
Working with VUE and MaterializeCSS I'm having problems using since I need to list a number of options from an array of objects filled in from an Ajax request but apparently VUE is hiding the information by creating a new under the main one.
Then I would like to know if anyone knows how to deactivate an element of the Materilizecss framework? In this case . Thank you.
If someone works for you:
Add the browser-default class to the but indicate in the display: block style because for some reason it hides it.
<select class="browser-default" style="display:block" v-model="category_id">
<option v-for="category in arrayCategories" :key="category.id" :value="category.id" v-text="category.name"></option>
</select>
Greetings.

Angular 2 - display one component as drop down in another and grabbing the selected value in parent component

This is my very first Angular 2 project. I created a component (category) that would pull a list of categories from a service stack API and show as a dropdown like this:
<select (change)="onSelect($event.target.value)" [(ngModel)]="selectedCategory.Id">
<option *ngFor="let category of categoriesToDisplay"
value={{category.Id}}>{{category.Name}}
</option>
</select>
Selected Category is: {{selectedCategory.Id}} and Name is {{selectedCategory.Name}}
I have another component (AddExpense) which is a form, where the user can add in the amount, category and hit submit that would POST to another endpoint. For AddExpense component, this is how the .html looks
<form [formGroup]="expense" (ngSubmit)="fileExpense($event)">
Spent <input type="number" formControlName="amt" />
for <input type="text" formControlName="name" />
on <input type="date" formControlName="transdate" />
and file it under category <show-category></show-category>
<button type="submit">Add Expense</button>
</form>
My question is how do I figure out which category from the drop down was selected in the add expense form, when the drop down itself is rendered via the show-category component and pass it on as a form control item for add-expense component's .ts to use?
I might be needing to use the Input and output decorator, but not sure how to nab that particular item thats selected in the dropdown and pass it on as input to the add expense component.
Sounds like you're displaying your first component (ShowCategory) in the second (AddExpense).
Now there is a couple way to do this,
The most obvious is to use Output, ShowCategory will then emit (See EventEmitter and Output example) whenever the selected value is changed.
In the template of AddExpense, you'd simply have to write something like this,
<show-category (change)="category = $event.category"></show-category>
But that's ugly, and frankly it would've been cool if we can do this and let Angular handle the two-way binding,
<show-category [(ngModel)]="category"></show-category>
Turns out it's doable, you can check out documentation for NgModel here, but what's actually useful is an example implementation for a real control like a checkbox
You might've noticed in the example that NgModel is not mentioned anywhere, and that's because we only have to create the mechanism for NgModel to write/read value from your component.
If you search on Google for NgModel ValueAccessor, there's a bunch of blog posts to help you out.
Lastly, I personally doesn't suggest doing what you're doing now if the ShowCategory component is that simple, that increases complexity a little bit, and ShowCategory isn't doing much for now. But what you provided might very well be a minimum working example, so what do I know.
Happy coding!

Does Materializecss Framewok destroy some critical properties of SELECTS?

The issue is this:
In my APP, I need to knw if a SELECT element is visible or not in the DOM under the MATERIALIZE framework. (Please do not mark this question as already discussed in here until you read it until the end.
So far I have been using document.getElementById('xx').offsetParent!==null to check that, and it has worked fine for me so far.
However, since I migrated my HTML code to Materializecss, my visiblity checking function does not work anymore.
This piece of code works perfectly in pure HTML
<div class='input-field col s12'>
<select name='V18' id='V18' />
<option value='' disabled selected>Select</option>
<option id='V18_1' value='1'>Choice 1</option>
<option id='V18_2' value='2'>Choice 2</option>
<option id='V18_3' value='3'>Choice 3</option>
</select>
</div>
<script>
if
(document.getElementById('V18').offsetParent!==null){
alert('Select is visible');
}else{
alert('Select is NOT visible');
}
</script>
Once I initialize the Selects in Materialize css, by calling the function $('select').material_select(), my visibilty checking function does not work anymore.
I have already tested all the options discussed on these links, and none of them work for Materialize selects:
Check if element is visible in DOM
How do I check if an element is hidden in jQuery?
My, question is...How can I check if a SELECT element is visible or not within the Materialize Framework? Seems that after initializing the selects, they loose some critical Javascript properties, somehow.
Does anyone have the same problem?
The workaround that I found for materializecss was to treat selects in a different way from radion buttons and texts,
For selects I detect visibility by using: window.getComputedStyle(element)).display === 'none'
For the rest kind of elements I detect visibility by using: "document.getElementById(element).offsetParent!==null"

django-autocomplete-light how to copy multi select fields

I'm using django-autocomplete-light with django 1.8.
I want to be able to copy the selected contents from one autocomplete field into another which requires overriding javascript code.
I tried duplicating the html content inside the autocomplete tool into another one in the browser debugger which looked good but when I click the save button in the admin page, it ignores my copied value.
Any ideas?
It works if you use an empty form for #form_template as such:
<div class = 'table' id="form_template" style="display:none">
{{ formset.empty_form }}
</div>
<div class = 'table'>
<table>
<!-- don't use #form_template in your actual form -->
From github issue

How do I use html labels with dijit/form widgets?

Ok, so I'm building an app using Dojo 1.8, and I have a custom widget with a template similar to this...
<div>
<label for="tag">Select something: </label>
<select id="tag"
data-dojo-attach-point="tag"
data-dojo-type="dijit/form/Select">
<option value="0">option 0</option>
<option value="1">option 1</option>
</select>
</div>
However, when the template gets rendered, the widget defines a new id, which makes the tag useless. I've tried googling this, but all my searches just direct to the Dojo documentation since they have attributes called labels but have nothing to do with the HTML label tag.
What is the proper why to do this?
In the situation you describe, you can simply place the label around your <select> and dispose with the for/id attributes. see Stackoverflow question:
How do I align two dojo widgets next to each other?, also see: w3 tutorial on label use
Also, if you want to actually use Ids in a widget template, see:
How do I create unique IDs in a Dojo widget template?
Using ids directly (ie. hard-coding them, not assigning them on-the-fly as in the above link) is not encouraged. The reason for this is that a template is meant to used over and over again in the creation of widgets.
In theory, it could be used to create multiple widgets on one page. Hence, in that situation you would have an id conflict. Each HTML id, on any one page, needs to be unique.