Ideas for inline templating in regards to a paged array binder...

276 views
Skip to first unread message

Lance Wynn

unread,
Feb 13, 2011, 12:17:21 PM2/13/11
to KnockoutJS
Hello All,

I am really going nuts with this knockout, thanks again Steve it
literally saved my latest project!

Anyway, I wanted to start a new discussion as I am wanting to develop
a paged array binder. I was going to base it on the each binder I
have been working on. In thinking this problem through, I really want
to focus on the markup syntax of the binder. I have not been a huge
fan of the template binding (sorry Steve, it's the one part of the lib
I am not 110% in love with) because 1, you MUST identify the template
by the id, and 2 because (at least with jquery template) there is a
secondary pseudo-markup syntax that you need to be familiar with.
However, in working through what will be required for a paged binder,
I think one would need at least 3 seperate templates. One for the
header, one for each item, and one for the pager. So, how does one
implement a nice clean markup syntax that gives the flexibility to
describe, and customize the look, but is simple to read, and doesn't
break the MVVM pattern?

I was thinking of using (and I'm not sure this will work on all
browsers) custom elements to markup the template parts, so the end
result would be something like (html):

<table data-bind="each: {data: myarray, itemsPerPage: itemsPerPage,
currentPage: 1}">
<headerTemplate>
<tr>
<th>column1</th>
<th>column2</th>
</tr>
</headerTemplate>
<bodyTemplate>
<tr>
<td data-bind="text: field1"></td>
<td data-bind="text: field2"></td>
</tr>
</bodyTemplate>
<pagerTemplate>
<tr>
<td colspan=2>
<span data-bind="click: showFirst, visible:
hasPrevious">Previous</span>
<span data-bind="click: showPrevious, visible:
hasPrevious">Previous</span>
<span data-bind="each: page>
<span data-bind="click: showPage, text:
pageNumber"></span>
</span>
<span data-bind="click: showNext, visible:
hasNext">Next</span>
<span data-bind="click: showLast, visible:
hasNext">Next</span>
</td>
</tr>
</pagerTemplate>
</table>

I think one of the really interesting points of something like this
would be the ability to use the same binder with all sorts of html
elements, so one could easily modify the look of the pager to display
whatever is needed, it could be a table as in my example, it could be
a paged list of images, it could be a tree view with a paged branch
(if so some crazy reason you wanted it). You could even have a paged
array within a paged array. So if you have a list of people, and each
person has an order history, you could display that order history as a
paged array within the paged item very easily without having to worry
about wiring up a lot of helper code.

The markup syntax I am proposing would still allow one to use external
templates by specifying the template id in the binder: data-
bind="pagedEach: {data: myarray, itemsPerPage: itemsPerPage,
currentPage: 1, pagerTemplate: 'standardPagerTemplate'}" so you could
maintain a list of page, or site-wide templates, and easily reuse
them.

I hope to hear comments on this plan, I think tomorrow if I have some
time I am going to start playing with it in earnest.

Thanks
Lance

Charlie K

unread,
Feb 13, 2011, 12:47:16 PM2/13/11
to KnockoutJS
I may not be following exactly what you want to get done but it seems
like your "each" or "forEach" bindings would work well for the
looping, why not just create a "pages" and "pageSizes" binding which
generates the elements based on the pages array? I think you could do
a lot with a "conventional" approach on this using data attributes and
jQuery.

I'm starting to think of bindings as the behavior, the model subset as
the configuration and the combination results in controls that make
the page work.

Charlie K

unread,
Feb 13, 2011, 12:50:29 PM2/13/11
to KnockoutJS
Another thing to consider is the single responsibility principle, the
proposed pagedEach binding tries to do a lot.

Lance Wynn

unread,
Feb 14, 2011, 6:10:56 PM2/14/11
to KnockoutJS
Thanks for the input Charlie, howeve I don't know that I agree with
all the points you make.

1. Sure it is possible to do with a conventional approach using
jquery, but that's true of anything that is done with knockout.
2. I don't agree that the binding is the behavior. In my mind, the
behavior is supplied by the viewModel in the form of commands,
observables, and dependentObservables. The binding is simply the
mechanism that renders the viewModel and allows the ui to interact
with it.
3. As for the single responsibility principle, that is great for core
functionallity, but this binder endeavors to be an abstraction to
provide a nice set of commonly used functionallity in a highly
accessible package.

Anyway, here is the sandbox version I put together today to help with
some issues in the current project. It is intentionally minimally
styled to show the functionallity.

Please let me know what you think...Of course it's poorly documented,
and I can't say it will work for all situations, but it is a start ;-)

http://jsfiddle.net/lancewynn/TDQRd/

Charlie K

unread,
Feb 14, 2011, 7:37:03 PM2/14/11
to KnockoutJS
"2. I don't agree that the binding is the behavior. In my mind, the
behavior is supplied by the viewModel in the form of commands,
observables, and dependentObservables. The binding is simply the
mechanism that renders the viewModel and allows the ui to interact
with it. "

That was well stated. I agree with you on the behavior is supplied
by the viewModel. I also didn't get what you were trying to do, the
fiddle looks cool. I think the problem was that I didn't understand
your dataContext binding. It appears that you have switched the
context and the pagedArray binding has introduced it's own built in
methods on the new dataContext, very interesting!

rpn

unread,
Feb 14, 2011, 9:58:08 PM2/14/11
to KnockoutJS
Very interesting Lance. Nice work!

Ω Alisson

unread,
Feb 15, 2011, 6:24:28 AM2/15/11
to knock...@googlegroups.com
Hey Lance, does your plugin works with multiple pagedArrays on the same context?

There is a typo on the property "nearbyPageRage"

Lance Wynn

unread,
Feb 15, 2011, 10:39:36 AM2/15/11
to KnockoutJS
Hi Alisson,
It can render multiple paged lists for the same array on the same page
without any problem. I did find a bug this morning wherein if you
tried to embed another paged array within the item of a parent paged
array, it was having issues with the templating. I fixed that, and
updated the fiddle. I also included a diabolical laugh in there
because it was really cool to see it actually work.

Anyway, please take a look at the fiddle: http://jsfiddle.net/TDQRd/8/
and let me know what you think.

Thanks
Lance
> > >http://jsfiddle.net/lancewynn/TDQRd/- Hide quoted text -
>
> - Show quoted text -

Lance Wynn

unread,
Feb 16, 2011, 12:24:07 AM2/16/11
to KnockoutJS
Also, I updated the fiddle to fix the nearbyPageRage typo:

http://jsfiddle.net/TDQRd/11/

Thanks
Lance
> > > >http://jsfiddle.net/lancewynn/TDQRd/-Hide quoted text -

Peter S

unread,
Feb 21, 2011, 6:56:01 AM2/21/11
to KnockoutJS
Hi Lance,

I've been having a play with your paged binder and am really impressed
by it but I have a couple of observations:

1. It doesn't seem to implement the _destroy functionality the
standard template binder uses to hide rows. I'm using this to tell the
server which rows to delete when I send the JSON back so having this
would be really useful to me.
2. Deleting a row from the middle of the array incurs a significant
performance penalty. For example, I have a paged grid with 200 rows,
broken into pages with 25 items per page. It takes 250ms to produce
the initial display but when I delete the first row it takes 1.4
seconds to update. I'm not sure why it would take so much longer to do
this than the initial display?

Regards,

Pete
> > > > >http://jsfiddle.net/lancewynn/TDQRd/-Hidequoted text -

Lance Wynn

unread,
Feb 24, 2011, 11:05:20 PM2/24/11
to KnockoutJS
Hi Peter,
Sorry it took so long to get back to you. My last project ended, and
I have been moved to a WPF project, so I haven't had much time to work
with knockout the past week. As for your issues:

1. My last project was .Net MVC, and we did not use the destroy
method, so I did not even think about it. That adds an interesting
twist to the pager. I'll see if I can find time to figure it out. As
a short term fix, maybe you could hide the row if destroy is true in
the itemTemplate? I don't know how that would work, but it might.

2. I can't seem to duplicate this issue. http://jsfiddle.net/TDQRd/13/
I added remove buttons to each item, and if I go to the 600th page
(10,000 records) and remove, it renders very quickly. Can you post a
sample of the performance issue? I don't know if I can solve it,
Javascript is certainly one of my weaknesses, but I'd like to give it
a try if I have time.

Thanks
Lance
> > > > > >http://jsfiddle.net/lancewynn/TDQRd/-Hidequotedtext -
>
> > > > - Show quoted text -- Hide quoted text -

Peter S

unread,
Mar 1, 2011, 4:18:11 AM3/1/11
to KnockoutJS
Hi Lance,

Thanks for the reply. Your sample does indeed seem very quick, I'm not
sure what I was doing that made mine so slow, I seem to have
overwritten whatever I was trying at the time so I'm not sure what I
did different.

I'm also using ASP.NET MVC but I find the _destroy feature quite
useful, I also use a similar _update and _insert flag in my bindings
then I can just tell my data service what's changed when I get the
data back as JSON. Actually I'd be interested to know how you deal
with the data once you get it back, how do you know what's been
deleted / changed?
Anyway, I've managed to implement my functionality in a slightly
different way so don't worry about it if you've moved onto other
things.

Cheers,
Pete

On Feb 25, 4:05 am, Lance Wynn <lance.w...@stgutah.com> wrote:
> Hi Peter,
> Sorry it took so long to get back to you.  My last project ended, and
> I have been moved to a WPF project, so I haven't had much time to work
> with knockout the past week. As for your issues:
>
> 1.  My last project was .Net MVC, and we did not use the destroy
> method, so I did not even think about it.  That adds an interesting
> twist to the pager.  I'll see if I can find time to figure it out.  As
> a short term fix, maybe you could hide the row if destroy is true in
> the itemTemplate?  I don't know how that would work, but it might.
>
> 2.  I can't seem to duplicate this issue.http://jsfiddle.net/TDQRd/13/

Lance Wynn

unread,
Mar 1, 2011, 10:46:03 AM3/1/11
to KnockoutJS
Hi Peter,

On my last project, there wer a bunch of business rules tied to
inserting records, so it wasn't as simple as adding a bunch of rows,
and then pushing them to the server. So we implemented the behavior
that when a user added a row, it would execute an ajax call to create
the row server side, and append the resultant json object to the array
when it was inserted. There were no "Save" buttons in the app, so
changes persisted fairly instantaneously.

Lance.

Chad Tolkien

unread,
Apr 19, 2011, 12:12:13 AM4/19/11
to knock...@googlegroups.com
Hi all,

First post, this is a fantastic binder Lance. Thanks for your contribution.

I've a question, I'm using this to build some tables, and I want to apply a  'zebra' class to every other TR, something to the effect of:

<tr data-bind="css : { zebra : (pageNumber % 2)  }">
This doesn't work because this is run inside the "itemTemplate", which doesn't have access to the pageNumber property. Any clues as to the best solution? The model I'm binding to doesn't have any sort of index ID available.

Lance Wynn

unread,
Jun 15, 2011, 3:57:57 PM6/15/11
to KnockoutJS
Hi Chad,
Sorry for the lateness in replying, I have been on a Non-Javascript
project for the past few months, and I have not had time to spend on
this. Did you find a solution? It should be possible to tweak the
binder such that each item also has a row property that contains the
row relative to the page. I'd need to dust off my code to see, but as
I recall this should be pretty easy to do.

Lance
Reply all
Reply to author
Forward
0 new messages