Undo/Redo framework

683 views
Skip to first unread message

Sergey

unread,
Mar 22, 2011, 10:57:38 AM3/22/11
to KnockoutJS
Hello!
I really love knockoutJs, that's great plugin. However, I have a
question.
Are there the best practices for Undo/Redo implementation if Knockouts
is used?
I.e. in your Hello World example - I would like to add the buttons
Undo/Redo. After I changed the values in the input boxes and the model
is updated I can click undo and return the old values, then click redo
and return to the newest values..
I thought that "subscribe" may help - I would catch the old and new
value and put the new undo unit in the stack..however, only NewValue
is passed in subscribe callback..
What do you think about adding the extended callback, so that I can
write something like:
myViewModel.personName.subscribe(function(oldValue, newValue) {
// do something with old value/new value
});
?

rpn

unread,
Mar 22, 2011, 11:04:05 AM3/22/11
to knock...@googlegroups.com, Sergey
Hi Sergery-
I don't know if this is exactly what you had in mind, but I had posted some thoughts that I had about this topic here: http://www.knockmeout.net/2011/03/guard-your-model-accept-or-cancel-edits.html

If this isn't quite what you are thinking, let me know and maybe we can explore other ideas.  Hope this helps.

rpn

unread,
Mar 22, 2011, 11:06:12 AM3/22/11
to knock...@googlegroups.com, Sergey
The method that I described would obviously need some modifications to track a stack of undo/redo values.

Sergey

unread,
Mar 22, 2011, 11:29:31 AM3/22/11
to KnockoutJS
Thank you very much for the prompt reply and the useful link. The
approach described there seems to be suitable for undo/redo
framework!. I will check it in more details tomorrow and let you know
about the results.

On Mar 22, 9:04 pm, rpn <rnieme...@gmail.com> wrote:
> Hi Sergery-
> I don't know if this is exactly what you had in mind, but I had posted some
> thoughts that I had about this topic here:http://www.knockmeout.net/2011/03/guard-your-model-accept-or-cancel-e...

rpn

unread,
Mar 22, 2011, 1:06:04 PM3/22/11
to knock...@googlegroups.com, Sergey
I'll be interested to see what you come up with.  Here was my quick attempt: http://jsfiddle.net/rniemeyer/4B9EP/


Sergey

unread,
Mar 23, 2011, 12:36:15 AM3/23/11
to KnockoutJS
I was able to implement the simple undo/redo sample by using the
wrapper for the observable, here is the sources.
http://jsfiddle.net/Tcbtp/2/

I think that approach will work fine in my real-world application.
Thanks again!

Btw - do you know is there a way to get the hightlight/intellisense
working inside the templates in Visual Studio?
In VS.NET 2010 the intellisense and the hightlight do not appear for
the fragments inside
<script type="text/html">
because the type of script is not well-known...

Sergey

unread,
Mar 23, 2011, 12:50:31 AM3/23/11
to KnockoutJS
http://jsfiddle.net/Tcbtp/3/ is more working version which works with
multiple updates :-)

On 23 мар, 10:36, Sergey <s.abakum...@gmail.com> wrote:
> I was able to implement the simple undo/redo sample by using the
> wrapper for the observable, here is the sources.http://jsfiddle.net/Tcbtp/2/

rpn

unread,
Mar 23, 2011, 3:58:05 AM3/23/11
to knock...@googlegroups.com, Sergey
Nice!  I think that I posted the wrong link before or overwrote it at some point, here was my try at it: http://jsfiddle.net/rniemeyer/SsVxQ/

Sergey

unread,
Mar 23, 2011, 4:10:36 AM3/23/11
to KnockoutJS
Cool beans, perhaps creating the wrappers around ko.observable for the
advanced scenarios like undo/redo should be declared as one of the
superB features of the product on the web-site :-)

In addition to my question about VS.NET 2010 intellisense - do you
know the way to declare the templates in external files and somehow
include them in the main html?
I.e. in js file I define the template:
<script type="text/html" id='myTemplate'>
.... template
</script/

and then include it in the main Html that uses the template in the
data-binding...including by the reference, like for regular scripts
does not work:
<script type="text/html" src="myTemplate.js"></script>
probably because of text/html type...

Vin

unread,
Mar 23, 2011, 12:36:26 PM3/23/11
to knock...@googlegroups.com, Sergey
I was looking for solutions to the same design/dev time abilities that Sergey is asking for.

1. Need a way to treat markup inside script templates of type x-jquery-tmpl or text/html just like script blogs or html blocks preferably in VS2010 (Intellisense, syntax highlighting etc) - couldn't find any VS Extensions for this in the VS Extensions Gallery
2. Need a way to include external templates in the main html by way of importing them and not mixing them inplace inside the html per se. - From this thread on StackOverflow it looks like currently it can be done by Response.Write(htmlTemplates) on the server side - which works, but it would be nicer if it was done client side.

Thoughts?

Vin

unread,
Mar 23, 2011, 12:38:22 PM3/23/11
to knock...@googlegroups.com, Sergey

rpn

unread,
Mar 23, 2011, 1:36:58 PM3/23/11
to knock...@googlegroups.com, Sergey
I have some thoughts and ideas on this that I am trying to get into a useful form.  Hopefully, will post some details tonight.  

Basically, I was thinking about 3 different ways or levels to do this type of thing:
  • Level 1- Put templates into .html files without script tags.  This will give you intellisense, etc. in VS2010.  Then, from the client side load the .html files and inject each into the page inside a script tag with an appropriate ID.  Ensure that all are loaded prior to calling ko.applyBindings
  • Level 2- Put templates into .html files without script tags.  Use MSBUILD to process the individual template files on each build into a single consolidated html file with script tags.  From the client side load the single html file and inject the elements directly into the page (script tags are already there).  This way you get design time support in the template files, but only have to do a single AJAX request for the content.
  • Level 3- Put templates into .html files without script tags.  Use MSBUILD to produce a js file that includes string versions of the templates and injects them into the document.  This way you get design time support in the template files and you can load it directly in a script tag. 

Vin

unread,
Mar 23, 2011, 2:21:51 PM3/23/11
to knock...@googlegroups.com, Sergey
I did some looking around and I agree with your options, for now, I decided to go with Level 1 approach

1. Define all templates in a single html file - this can become a problem if there are dozens of them, but for now I have a few.
2. On the client side inside $(document).ready after defining the viewModel etc, run the following code, notice the applyBindings is called inside a callback, that way the templates are already loaded in to the DOM.

$.get('UITemplates.htm'function (templates) {
    $('body').append(templates);
ko.applyBindings(viewModel);
});

3. Next step is to strip the script tags from the UITemplates.htm (for intellisense or syntax highlighting needs), add the script container blocks in the main html file, and add logic in the above code to loop through each script blocks using ids and then append them to corresponding script container blocks in the main.html

Looking forward to more insights in your blog post.

Sergey

unread,
Mar 23, 2011, 10:26:40 PM3/23/11
to KnockoutJS
Hi guys,
Let me put my $0.02 in..
My real-world project is jQuery plugin. End-user will have to include
the js script that contains templates, view models, etc. code and then
write something like:
<div id="container" style="width:500px, height:300px" />
<script type="text/javascript">
jQuery("#container").myPlugin();
</script>
my plugin will add data-bind="template:'my template'" attribute in the
"container" div and invoke ko.applyBindings(viewModel). I believe that
it will work OK, if it doesn't - will let you know..

I realized that all the templates should be in my script in form of
strings. I would append the strings to the body in myPlugin "_init"
function then.

during the development I will use html files without <script>
tag(which gives me highligh, intellisense) and then translate them to
the escaped strings and include in the resulting JS files along with
view models and other code from other js files by using Nant or
MsBuild script(thanks for this tip).



rpn

unread,
Mar 23, 2011, 10:41:50 PM3/23/11
to knock...@googlegroups.com, Sergey
Here are my ideas about loading external scripts for use in Knockout: http://www.knockmeout.net/2011/03/using-external-jquery-template-files.html

Sergey- let us know how it goes for your plugin.  Good luck!

maor...@gmail.com

unread,
Mar 2, 2014, 8:30:07 AM3/2/14
to knock...@googlegroups.com, s.aba...@gmail.com

We Have a small extension to Knockout.js as part out project that extends observables so they can be registered to different stacks of there history.

Maybe it can help you.

Knockout-Memento

ziad...@gmail.com

unread,
Sep 27, 2014, 4:53:32 AM9/27/14
to knock...@googlegroups.com, s.aba...@gmail.com
Here's a working example I made for those needing undo/redo functionality:

http://plnkr.co/edit/nB2129?p=preview

It's based on the deep change tracking ko-reactor plugin
Reply all
Reply to author
Forward
0 new messages