I've been working on some webapp where i have a table which is filled with some data and to select which data should be displayed i use filters. These filters are <div> elemtens which contain one <div> per filter option like so:
<div id="selectedFilter">
<div>
<input id="selectedFilter1" type="checkbox" name="selectedFilter" multiple="true" value="1" checked="true">
<label for="selectedFilter1" title="Option1">Option1</label>
</div>
<div>
<input id="selectedFilter2" type="checkbox" name="selectedFilter" multiple="true" value="2" checked="true">
<label for="selectedFilter2" title="Option2">Option2</label>
</div>
<div>
The html code for the options (the whole <div> with <label> and <input> ) is generated in my java backend and gets transferred to the site like this:
$.post("filter", result, function(data) {
$("#selectedFilter").html(data);
});
Now my problem:
The amount of filters gets sometimes really high (e.g. 800 rows) and there are two more filters on the page with about the same amount of options. With such a load of data the browser begins to hang and becomes unresponsive.
To fix this i tried using virtual scrolling since this seems to be the most reasonable way to keep the browsercache on a good level. But this clears the checkboxes, if i render the whole div again.
On top of that i need to know which checkboxes are checked even if they are not in the viewport because the filters are influencing each others possible options in a cascading manner (Filter1 influences Filter2 influences Filter3). If one filter changes (something gets selected) the subsequent one (or two) gets cleared and requests new data from the java backend.
Question:
Is there maybe a js-library which supports the virtual scrolling but manages the checkboxes by itself so i can extract just the checked ones? Something like this.
I might try to save which chechbox was selected but i fear that the virtualisation of the scrolling might be very slow if there is a matching of the displayed options whether they are checked or not in every single scroll.
Does anybody have suggestions or experiences?
You are saying you are having 800 filters , do you really think any user gonna see all those 800 or more filters together. The best thing is to categories your filters and then load them on click of category.
Virtual Scrolling is good idea. You need to append filter data as .html() is overriding your previous content.
$("#selectedFilter").append(data);
Related
I got an old angular js application and my mission is to fix accessibilty problems. I have a table that includes radio buttons within the cells and I need to navigate between them using the arrow up and down keys.
I already have a method that deals with this issue and its working fine until i test it using screen reader (NVDA)
What happens is for some reason the SR cause the method to be ignored
and causes the table to lose its focus.
the only way that I managed to make it work is by setting the table with role="application".
but from what I have been reading so far it is wrong to use it in this case
This is a sample of one of the cells :
<td class="scheduleLineCell" style="text-align: center;">
<input type="radio"
class="btnRadio ng-valid ng-not-empty ng-touched ng-dirty"
aria-describedby=""
value="126" data-ng-model="selectedIdList[childSchedule.gridIndex]"
data-ng-key-press="scheduleKeyPress"
data-ng-grid-index="0"
xng-focus="isFocusOnStationButton == false &&
isFocusOnMapButton == false && ScheduleLine.Id ==
selectedIdList[search.currentScheduleGridIndex]" name="2096">
</td>
Can you make a working example on here or on JSfiddler?
Off the top of my head I can say this.
You should not put controls in tables or uses tables for design purposes.
a. If you have an enter data row make it from "div"s
b. Remember screen readers repeat table headers a lot!
JAWS and NVDA does mess with a screens JSEvents and get us a example page to help
(AngularJS) Refactor the control back to a component or directive and see if that helps.
a. e.g.
<custom-radio-button ng-value="val" aria-checked="true"></custom-radio-button>
So I have a table with 50 columns and about 4-600 rows and laggy poor performance. There are some computed properties in use. The tables cells are inputs, selects and textareas.
I use the vue-scrolling-table, because I need vertical and horizontal scrolling, and fixed first column. But the performance is really bad.
I also have the same setup, somewhere else is the app, but it doesn't have the same performance issues.
I already tried to use a virtual list, but I could'nt get it working with the vue-scrolling-table/ (the header didn't follow the scrolling, and the vertical scroller was only available if I scroll to the bottom)
I also looked at virtual scroller but it recomanded not to use with inputs and such, since it is replacing the data inside the input, and that would trigger the change event etc.
I have a v-for, that goes through the data, and one v-for inside, for a subset in the columns. (I can't be sure how many columns there will be.)
<template slot="tbody">
<tr v-for="(row,index) in table" :key="index">
<td>
<input v-model="table[index].someItem">
</td>
<td>
<select v-model="listyThing">
<option v-for="item in list">{{item}}<option>
</select>
</td>
...
# I have some computed stuff ,(like 4)
SomeComputedFunction: function() {
return this.table.map((row) => {
return row.some * row.somethingelse
})
}
This should work fine. The data I'm working with is not that big, that it should cause problems. I try to do anything in this, and the cpu spins up to 100% and everything happens with 2s delays.
Also one interesting thing I found, the selects open in like 3 secs. I thought that was curious.
When I used the virtual list the performance was better, but I need some other solution for the table.
Does anyone have an idea what is the difference between this, and my other one which works just fine (more data and more computed properties actually)
So what I think the difference can be is the selects and the v-for rendered columns (about 20 of them rendered this way). Or maybe the textareas?
Thanks in advance!
I have a table with variable number of records (could be up to hundreds) where its body is build with one ng-repeat.
Within each record, there are two input fields of type select where their contents is also built using ng-repear and the number of options for each is about 100.
This is working right now, except that it takes a lot of time for the page to be built (several seconds; I guess due to the large number of html records that AngularJS is adding to the DOM).
Here is an example of one of the selects:
<select class="form-control" ng-model="One_Source.Measuring_Method_Code">
<option ng-selected="{{One_Method.Value == One_Source.Measuring_Method_Code}}"
ng-repeat="One_Method in All_Collections.Parameters_Test_Methods"
value="{{One_Method.Value}}"
title="{{One_Method.Test_Method_Name}} | {{One_Method.Method_Internal_Name}}">
{{One_Method.Value}}
</option>
</select>
Two questions:
Is there a simple way to speed up the page building process?
As shown in the example, each option in the list has a title clause displaying a detailed description of the option's meaning. How can I add a title to the select showing the description of the current value?
For the first question I was thinking about building the list of options for each select element only upon clicking on it, but I'm not sure if that would be the best way to do it.
Try using one time bindings so that Angular doesn't watch the value by prefixing it with ::. It can also be more efficient to use track by in your ng-repeat if each row has a unique value, like an ID.
<option
ng-selected="{{One_Method.Value == One_Source.Measuring_Method_Code}}"
ng-repeat="One_Method in All_Collections.Parameters_Test_Methods track by One_Method.id"
value="{{::One_Method.Value}}"
title="{{::One_Method.Test_Method_Name}} | {{::One_Method.Method_Internal_Name}}"
>
{{::One_Method.Value}}
</option>
If you still can't gain the performance you're expecting from #doublesharps's answer, you will have to implement one of the following:
You could build a custom list that has a 'load more' button which would destroy say the first '50' options and load the next 50.
A better option would be to turn this into an autocomplete, where the user searches for values.
Virtual repeat - Something angular material does really well, it constantly draw's and re-draws new elements based on the scroll position inside the element.
Other resources:
http://blog.scalyr.com/2013/10/angularjs-1200ms-to-35ms/
https://github.com/stackfull/angular-virtual-scroll
http://klajd.github.io/angular-virtual-repeat/#/Home
I found a PARTIAL SOLUTION that still needs to be polished but is quite promising.
During creation of the page, I do not make use of ng-repeat for the options but instead deploy a single option with the value received for the field from the database (if any, otherwise the select element is left blank).
When the user clicks on the select element a $scope function is invoked that checks the number of options within the select element and, if less or equal to 1, the inner HTML of this select element is re-generated and deployed.
Though clicking on all these select in the page will take (accumulative) a comparable time as when built upon load, this time is distributed over several events (the user clicking on all the select elements) and hence it is not perceived by the user.
Now, by polishing I mean that there is a strange behavior. In order to see the generated list of options, I need to click on the select twice. Will keep investigating this and post the solution (hoping I find one).
I have three dropdown select boxes. Each contains a different set of demographic attributes. I'd like to display a score corresponding to whatever combination of selections is made by a user. For example, if a user selects Male, 18-24, Asian-American, I want to hide the current div and display the div corresponding to that combination.
I have seen answers for how to do this with just one select box, but since I have three and there are significantly more combinations, I wanted to see if there was a simple way to do this efficiently. I can provide specific code if needed, though a general example of how to do this would be just fine as well - thanks!
Keeping hidden divs for all possible combinations is not a good idea. That will make your page size bigger. Why don't you get only the relevant information as needed using ajax and show it ?
In your page, keep only one div to show the information
<select id="Age">
<option value='1'>18-24</option>
<option value='2'>25-50</option>
</select>
<select id="Place">
<option value='1'>Asia</option>
<option value='2'>America</option>
</select>
<div id="info"></div>
Now listen to the change event of the dropdowns, get the selected value of dropdowns and make an an ajax call to the server page and get the markup to show to user. In the below script, I am using jquery load method to load the new markup in the info div.
$(function(){
$("#Age,#Place").change(function(e){
var age=$("#Age").val();
var place=$("#Place").val();
$("#info").load("yourServerPage.php?age="+age+"&place="+place);
});
});
Assuming you have a server page called yourServerPage.php which accepts the age and place from the querystring and return the markup for the information div.
I have a website on which I insert an select with option for the user to choose and each of the options picked will result in a change in the page background's color.
Also I have a navigator to move between 2 pages (for example, page with title "Tittle A" and another with the same DOM structure but its title "Title B")
The option includes "iA, iB, iC" items.
The problem is like this,
in page A, if I choose one option, e.g iB to change the background color, then I pick the navigator to select page B, I will still see the selected iB although the background is refreshed into page B.
Anyone any idea please. I believe this is a cached issue but I have no idea how to resolve this with maybe a piece of javascript [jquery] code or means to flush the cache each time the page is refreshed. Thank you
I think that it's a cache effect. To solve this problem try to select needle option by js. Something like this:
$(function(){
$('#your_option_id_for_example_iA').click();
})
It's due to a "feature" in modern browsers that remember you selection/input in input fields. It's called autocomplete. To prevent the browser to remember you choice, you need to turn it off. It can be done with HTML or JavaScript/jQuery.
HTML:
// For just a specific element
<input type="text" autocomplete="off" />
// For an entire form
<form autocomplete="off">
jQuery:
$('input, select').attr('autocomplete', 'off');
You can read more about it here:
https://developer.mozilla.org/en/docs/How_to_Turn_Off_Form_Autocompletion