In my application users define documents layouts.
These layouts are logically tables most of the time, so users specify which "property" is going to be displayed in which cell. They also can define a number of rows and columns as well as how many rows or columns a property will take (collspan and rowspan in HTML terminology).
Now for a given document layout, and a set of documents I need to display it in browser.
I would like to do it on the client side, possibly using jQuery or/and Knockout.js, or some other framework/library.
Before I start reinventing the wheel, can someone point me in the right direction of doing it?
Not sure if this really counts as a question. It's quite open to interpretation but here goes.
Define your LayoutViewmodel with a set of multi-dimensional observableArrays. Each index in the multidimentional array corresponds to a Property object which holds the data about rowspan, colspan etc (not sure what data you need).
Display you layout with foreach bindings. You most likely have two of these, one for selection and one for display. Below is my attempt at the display one.
<table data-bind="foreach: rows">
<tr data-bind="foreach: columns">
<td data-bind="attr: { colspan: colspan, rowspan: rowspan }, text: name">
</td>
</tr>
</table>
Hope this helps.
Related
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'm building a basic grid component with Angular 6. The grid itself is a <table>, with a <thead> for the header and a <tbody> section, where there are multiple rows. Each row has a fixed first column (which has de ID of the row), a dynamic number of 'positions' and a fixed last column (which holds an action combo button). Each of the positions contain a list of objects, dragged from an external tree component. All the rows, the positions and the list of objects inside them are generated from a DB, and displayed using *ngFor in the component template.
To make it clear, here's an schema of the grid:
The grid is built in this way:
<table #mainGrid>
<thead>
[...]
</thead>
<tbody (contextmenu)="showContextMenu($event)">
<tr *ngFor="let row of objectGrid; let i=index">
<td>{{ i }}</td>
<td *ngFor="let position of row.positions">
<ul class="object--list">
<li class="object--list--item" *ngFor="let object of position.objects">
{{ object.name}}
</li>
</ul>
</td>
<td><!-- CODE FOR THE ACTION BUTTON --></td>
</tr>
</tbody>
</table>
Each object has several actions associated to it (f.i. 'Delete', 'Locate in tree', 'Edit', etc) that must be chosen using the right button of the mouse. I'd like to avoid attaching an event handler to each object because sometimes the grid will contain more than 700 objects, so my idea is to attach only 1 contextmenu handler to the <tbody> (to disable right clicking on the table header) and use logic to find out the object where the user right clicked.
So far, I can use the event path property to identify the row, cell and the object (li element) where the right click occured. But now I'd like to know an elegant way of associating univocally the clicked li element to the position of the array that generated it.
For example, if I right click on the object 'Object 1.4.2', I'd like to get the reference to this.objectGrid[0].positions[3].objects[1].
Any suggestions? Thanks!
I couldn't find a safe way of doing it, so I've ended up adding the event handler to each of the objects that need it. So far, the performance for a grid with 500+ elements is pretty good, but I'm studying how to implement a virtualization to the grid component to load only the rows displayed on screen.
I have a search column which on searching shows multiple tables as results (by multiple I mean in 1000 or more) .
Problem - generated tables are shown in one page only, I want them to be shown in multiple pages for better readability. I also want to sort some columns of each table.
for example
in Views cshtml format I have something like this
<section class="someclass">
foreach(var item in something)
{
<table>
<tr>
<td>#item.a</td>
<td>#item.b</td>
</tr>
<tr>
<td>#item.c</td>
<td>#item.d</td>
</tr>
</table>
}
</section>
and the 'var' is generally very large in count so this code generates a lot of tables
any idea how I could do paging in this case
what I have tried :
well I have tried table sorter and i am confused how to implement that in a section..
apart from that I don't want to use server side options as I want keep the code in javascript only.
I want to create a html table that groups data using rowspan with ng-repeat.
The layout is working fine but I got a problem when I add filters to the table.
For example, when I filter the table by "Category" column with "STD" value it breaks the layout.
I have created this JsFiddle to show the issue.
Any recommended approach to manage this?
This is related with this question:
Best Regards.
I did not have much time to look on this, but is seems that your issue is here:
<tr ng-repeat-start="state in country.states | filter:{stateCode:stateCodeFilter}" ng-if="false"></tr>
<tr ng-repeat="city in filteredMappings = (state.cities | filter:{category:categoryCodeFilter})">
<th ng-if="$parent.$first && $first" rowspan="{{country.rowSpan}}">
{{country.countryCode}}
</th>
The $parent.$first is set to false in case of filter usage because $parent.$first is the first item in the not-filtered countries list but you never reach this one in the second repeater as it is removed by the filter. This leads to the first cell in the row being hidden and thus whole your table design is being deformed.
I do not have any quick solution on my mind right now, but I will take a look later if I find some time. Hope it helped you at least a bit.
I have not written the code yet, but wanted to know general direction. My entire front end consists of HTML tables. It actually has an excel look.
I was thinking of generating default pages and then using JS to shift entire rows and columns based on ids.
The table cells might contain - Label, Textboxes, Images, Checkboxes etc.
In what way should I address the row or with Javascript assemble a group of elements within the , tags. Do not want a solution with <div>
So if I write a <th> as
<th class="col1" colspan="1"><%= nodes.last == #map.keys.first ? label_tag("#{nodes.last.to_label}") : label_tag("#{nodes.last}") %></th>
I could give it an id, but then would selecting that elementbyId in JS cause for even the context of the row to be picked up
You can give every row an attribute contain Id number, then you can read this numbers in JQuery and Re-Sort your table.