Thursday, May 15, 2014

AngularJS: Create editable tables with dynamic columns (Part 3)

Further to my previous post, and as mentioned in Part 1, there are lots of different UI approaches to creating editable tables.

For example: a table where you click an edit button next to each row to open a pop-up window; a table where you click the row itself to open a pop-up window; a table where you click each row and edit it 'in place'; a table where all rows are editable at once; a table where each row has both an edit button and a delete button; etc. etc. I'm sure you can think of plenty more. All of them are valid choices depending on your UI design.

It's because of this that Metawidget doesn't try to 'own' your UI. Metawidget only strives to be a piece of your overall solution: a useful widget you can sprinkle liberally all over your UI, wherever you need UI generation, but nowhere that you don't.

The downside of this flexibility is that you have to do a bit more work to wire everything together. In this post I'm going to implement one of the above approaches: a table where all rows are editable at once. It's very similar to my previous post. This time, instead of the editable table instantiating a plain piece of HTML, it instantiates a Metawidget for every row and every column:

var columnMetawidget = $( '<metawidget ng-model="row.' + columns[loop] + '" config="metawidgetConfig">' );
tr1.append( $( '<td>' ).append( columnMetawidget ) );

This works because Metawidget is very lightweight. All parts of the metawidgetConfig are immutable, so the same objects are reused for every Metawidget in the table. The result looks like this:

You can download a complete example here. Feedback welcome!

UPDATE: the built-in metawidget.widgetbuilder.HtmlWidgetBuilder now supports alwaysUseNestedMetawidgetInTables which may be useful in these cases


Gianluca Stefanelli said...

Hi, I'm trying your example and I found it very interesting.
Just a simple a question:

Is it possible to pass dynamicaly with some variable the schema of json structure after the attribute "properties" ?


inspector: new metawidget.inspector.JsonSchemaInspector( {
properties: {
< schema>



Gianluca S.

Gianluca Stefanelli said...

How can change the width column in table passing the value of size dynamically ?

Richard Kennard said...

Hi Gianluca,

Re: dynamic schema properties

Yes, this is possible. Metawidget features a flexible, pluggable Inspection layer so you can plug-in whatever inspection results you want.

There are a few built-in Inspectors, such as PropertyTypeInspector and JsonSchemaInspector. But for your case you should write your own:

inspector: function( toInspect, type, names ) { ... }

Your function should look at the given toInspect, type and names to determine what to return. Here's an example that compares using JsonSchemaInspector to doing it manually:



Richard Kennard said...

Re: column widths

Yes, I can see how this would be generally useful. Now added in GitHub:

You can build it from there, or wait for the next nightly build (23-May-2014):

Gianluca Stefanelli said...

Great this is awesome, i'm going to try soon.
Another little issue.
Can you have a look to my code in this plunkr.

The problem is how can represent value in a table from differents format of json.


Gianluca S.

Gianluca Stefanelli said...

Richard Kennard said...

Can you please create a working test case for me to examine?

That Plunkr appears to be my project but with a main.js added into it, but not linked in any way? The index.html is still using my app.js

Gianluca Stefanelli said...

I've corrected the plukr with my test case.

Gianluca Stefanelli said...

Ok i solved it with a little workaround.
Here's the new plunkr.

Now i have to fix the way to remove the label "Row:" before the table.

Gianluca Stefanelli said...

Ok I solved it with a little workaround as you can see here in the new plunkr.

Now I just only fix the way to remove the label "Row:" before the table.


Richard Kennard said...

Apologies for the delay in replying.

The label is coming from the TableLayout. So in your Plunkr, instead of 'layout: _tableLayout' try 'layout: new metawidget.layout.SimpleLayout()'.

Or, if using Metawidget 3.9 (just released) you can add 'title: null' metadata to the 'row' property. TableLayout will take this to mean you don't want a label.