Dear Seasiders,
I must bee overlooking something obvious. I want to redraw a listItem in and unorderedList (it is a
boostrap .list-item .row, but that doesn't really matter) in an
Ajax callback. The ajax call is initiated in a javascript function, not rendered by Seaside. This call to ajax does the following;
$.ajax( ... ).done(function(result) { where row is a jquery that contains the listItem. The rerendering works very well and all seems good. Except for one little detail: the callbacks rendered in the AJax callback are re-numbered from 1 and once you click on oneof the re-rendered link it is a nice surprise what method might get called on the server. I guess I am messing with the _s and _k parameters in my caööback method. So here is my callback method which answers the re-rendered listItem/row:
changeSomeStuffOnTheServerAndRedraw | rahmenElementId fields req betrag planElement conv wrapper ctx contKey row resp | ctx := self requestContext. req := ctx request. resp := ctx response. fields := req fields. "Some boring business stuff which works like a charm, including finding the right business objects, changing them, commits in Glorp and whatnot""Re-render the row" row := self findTheListItemComponentForRerendering. resp status: 200; contentType: (WAMimeType textHtml charset: ctx handler charSet); nextPutAll: ( (self rendererClass builder) "**->" actionUrl: (ctx session actionUrlForKey: contKey); "I also tried leaving this out --> even worse" fullDocument: false; render: [:html | html render: row ])I think the problem is either the fact that I shouldn't be using the requestContext of the Ajax callback, or the actionUrl: part is wrong. The rows not re-rendered still work like a charm. You can see in the attached picture that both a not-re-rendered row and the re-rendered row point to the same 's anchors point to the same url with identical _s and _k parameters, but thesecond one is the re-rendered and its callback number is 1 instead of 51, which it had before re-rendering: If I use the URL and replace the 1 with 51, The correct callback is being called, the initial callback is still registered. I wouldn't mind if the re-render registered another Callback, even if that means I waste memory, but it seems I am registering the new callbacks in some registry that's new for the ajax callback.... (I am confused) Any hints? Ideas? How can I make sure the anchors in that redrawn listItem find their callback blocks on the server? Thank you in advance Joachim -- ----------------------------------------------------------------------- Objektfabrik Joachim Tuchel [hidden email] Fliederweg 1 http://www.objektfabrik.de D-71640 Ludwigsburg http://joachimtuchel.wordpress.com Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
Hi Joachim,
I’m a bit confused why you are rendering in this way in your callback method. Why are you doing this differently than in any other Seaside rendering method? Since you are instantiating a new builder, it is going to create it’s own rendercontext, hence it’s own registry for callbacks. I have not deeply investigated the result of your code snippet, but this seems to me why you are seeing that callback numbers are restarted. Now, if you re-render list-item with a callback on it, Seaside will indeed need to register a new callback. The memory overhead should be limited to the registry dictionary entry and a WASeasideCallback instance, however, since the block and it’s lexical context object will already exist before rendering. So… I would not worry about memory overhead. If you are doing this because you are doing hand-written ajax calls: what I tend to do is generate a jQuery-Seaside ajax callback and assign this to a Javascript variable, which I can use from the hand-written JS. Of course, there’s variations on this other than global-variable assignment but that’s all Javascript fiddling. So, before I try to dig deeper in your problem: why is this method not called: "changeSomeStuffOnTheServerAndRedrawOn: html” :) ? Johan
_______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
Hi Johan,
first of all: thanks for your time! > I’m a bit confused why you are rendering in this way in your callback method. Maybe the answer wouldn't really be something I'd like to hear ;-) The method doesn't have a parameter, because the ajax call is initiated by hand-written javascript code. One reason is that the list can be very long (up to 2000 list items) and I only want to install one click handler on the document using $(document).on("click",".mylistItemClass", function() { ... $.ajax() ...}).done(); etc. etc. So I register only one callback in updateRoot: and store the number in an instVar updateRoot: checkboxenCallback := html context callbacks store: (JSAjaxCallback on: [self einOderAusblendenCheckbox]). then, in renderContentOn; I do: renderContentOn: html document addLoadScript: ( '$(document).on("change", ".ein-aus", function(evt) { evt.preventDefault(); var target = $(evt.target); var row = target.parents(".row"); $.ajax({ url: %1+"&pk="+ rahmenId , }) .fail(function(res) {alert(res.responseText)}) .done(function(result) {row.replaceWith(result); }}); })' bindWith: (html actionUrl copy addField: checkboxenCallback) asString sstAsQuotedString) So I guess you are asking the right question: why do I build up a new context/builder... ? I never tried, but maybe I should just register a one argument-block as callback and hope for some Seaside magic? I will try that immediately (just occured to me while typing this message...) Joachim Am 11.02.17 um 09:11 schrieb Johan Brichau: Hi Joachim,
-- ----------------------------------------------------------------------- Objektfabrik Joachim Tuchel [hidden email] Fliederweg 1 http://www.objektfabrik.de D-71640 Ludwigsburg http://joachimtuchel.wordpress.com Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
Unfortunately, this one-argument block
idea doesn't work. If I register the Ajax callback with an
argument, the callback method will receive nil as parameter....
Am 11.02.17 um 09:32 schrieb [hidden email]:
-- ----------------------------------------------------------------------- Objektfabrik Joachim Tuchel [hidden email] Fliederweg 1 http://www.objektfabrik.de D-71640 Ludwigsburg http://joachimtuchel.wordpress.com Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
Hi Johan,
I am trying to decipher what you are encrypting in this message: > If you are doing this because you are doing hand-written ajax calls: > what I tend to do is generate a jQuery-Seaside ajax callback and > assign this to a Javascript variable, which I can use from the > hand-written JS. Of course, there’s variations on this other than > global-variable assignment but that’s all Javascript fiddling. > It seems you exactly describe the sitation I'm having here, but I am unable to translate it into working code. So you register a an Ajax Callback, nut that callback still is a zero argument block, or, if I not only provide the callback number in the url, but also a value for it (like 36=MyValue), the callback method will get this argument as a parameter, but no html builder...???? So it seems I will only understand what you suggest here if I see a code example. Do you happen to have one? Joachim -- ----------------------------------------------------------------------- Objektfabrik Joachim Tuchel mailto:[hidden email] Fliederweg 1 http://www.objektfabrik.de D-71640 Ludwigsburg http://joachimtuchel.wordpress.com Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
In reply to this post by jtuchel
Hey Joachim,
You can use a normal seaside callback and register it to capture delegated events. No magic ;) html orderedList script: (html jQuery this on: ‘click’ selector: ‘.mylistItemClass’ do: ((html jQuery ajax callback: [:listitemId | … ] value: (((html javascript alias: ‘event’) access: ‘target’) access: ‘id’)) asFunction: #(event)) This registers the callback on the list to capture clicks on the items below it, while passing the id of the element on which the click happened to the callback. If you register passengers on each of the listitems, it’s more intuitive: html orderedList script: (html jQuery this on: ‘click’ selector: ‘.mylistItemClass’ do: ((html jQuery ajax callback: [:passenger | … ] passengers: ((html javascript alias: ‘event’) access: ‘target’) asFunction: #(event)) Obviously, this does not render anything yet. So, we need to add that functionality to the callback: | idToReRender | html orderedList script: (html jQuery this on: ‘click’ selector: ‘.mylistItemClass’ do: ((html jQuery ajax callback: [:listitemId | … idToReRender := listitemId ... ] value: (((html javascript alias: ‘event’) access: ‘target’) access: ‘id’)); script: [:s | s << ((s jQuery id: idToReRender) html: [:h | self renderMyRowWithId: idToReRender ]) ] asFunction: #(event)) This adds a script callback that will produce a response that re-renders the list item. Although this is a rough implementation that passes id’s everywhere, it does require to keep a mapping between id and the ‘row item component’ you need to render somewhere in your app. Seaside provides such a mapping via passengers, but depending on your use case this might not scale either. So, how this mapping is done depends a bit on you. For more examples that use event delegation, take a look at this repo from the tutorial I gave at ESUG Edinburgh: http://smalltalkhub.com/#!/~JohanBrichau/Seaside-Playground The renderTodosOn: method has some exciting callback combinations to look at. Hope this helps Johan
_______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
In reply to this post by jtuchel
> It seems you exactly describe the sitation I'm having here, but I am unable to translate it into working code. So you register a an Ajax Callback, nut that callback still is a zero argument block, or, if I not only provide the callback number in the url, but also a value for it (like 36=MyValue), the callback method will get this argument as a parameter, but no html builder...???? Sorry for being cryptic; it’s not intentional ;) I think the key here is to combine callbacks (as I just sent you) and add one that Seaside supplies a html or script canvas to. But instead of combining, you can also chain them (using #onSuccess:). Hope this helps Johan _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
Am 11.02.17 um 10:22 schrieb Johan Brichau:
>> It seems you exactly describe the sitation I'm having here, but I am unable to translate it into working code. So you register a an Ajax Callback, nut that callback still is a zero argument block, or, if I not only provide the callback number in the url, but also a value for it (like 36=MyValue), the callback method will get this argument as a parameter, but no html builder...???? > > Sorry for being cryptic; it’s not intentional ;) I know. The crypticism is introduced in my brain ;-) _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
In reply to this post by Johan Brichau-2
Hi Johan,
okay, food for thought and experimenting. Thanks a lot. I'll be attempting to process this, expect me to not ask questions on this for a while ;-)))) Anyways, thanks a lot for these explanations and sample code. I'll have to chew on that for a while ;-) Joachim Am 11.02.17 um 10:19 schrieb Johan Brichau: Hey Joachim,
-- ----------------------------------------------------------------------- Objektfabrik Joachim Tuchel [hidden email] Fliederweg 1 http://www.objektfabrik.de D-71640 Ludwigsburg http://joachimtuchel.wordpress.com Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
In reply to this post by Johan Brichau-2
Hi Johan
Am 11.02.17 um 10:19 schrieb Johan Brichau: Hey Joachim,I seem to understand. This will call the server twice, once for the setting id of which item to rerender, and a second time for the actual rendering, right? My attempt tried to use the first ajax callback to do both: process the business code and answer the re-rendered row to the client, so that it just does a .replaceWith() for the row with the re-rendered one. That is why I needed to have a builder that the component could render itself onto. But since your aproach just registers one single callback for the whole list, it still is an improvement compared to registering the very same callback for each row - which takes a lot of time on both the server and the client. And apart from the double ajax calls, it is exactly what I want to achieve. I guess my reason for hand-written javascript here is that I like to be able to debug it and I know way too little about JQAjax' many options... time to study My brain is working on this, and I am really grateful for your time and help. I guess we should negotiate your reward in Maribor ;-) Joachim
-- ----------------------------------------------------------------------- Objektfabrik Joachim Tuchel [hidden email] Fliederweg 1 http://www.objektfabrik.de D-71640 Ludwigsburg http://joachimtuchel.wordpress.com Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
Hi Joachim,
Glad to hear you are decrypting all of this. Just to add: the code I sent really only does 1 ajax request from the client to the server. The trick is that there are two callbacks attached to the same request. Of course, you can only attach a single callback that produces a response (a primary callback). But you can attach as many secondary callbacks as you want (i.e. callback:value or callback:passengers:) to a single ajax request. Have a nice weekend! Johan
_______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
Hi Johan,
Am 11.02.17 um 10:51 schrieb Johan Brichau: Hi Joachim,I hope my comment wasn't offending you. Just an expression of me not understanding immediately... So this is something I really need to understand, besides all those little alias:/access: and other helpers.... Maybe this time ;-) I really need to play with this. So far, I tried doing as much as possible in hand-written JS because it is easier to read and debug than Seasides code-renderer-helpers. But as my case shows, there are situations in which you cannot get away with this approach... Same to you. You've had your Seaside Doctor's shift today ;-) Joachim
-- ----------------------------------------------------------------------- Objektfabrik Joachim Tuchel [hidden email] Fliederweg 1 http://www.objektfabrik.de D-71640 Ludwigsburg http://joachimtuchel.wordpress.com Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
In reply to this post by jtuchel
Hi Johan,
What can I say? Apart from a missing bracket and the fact that it is not "html jQuery this", but "html jQuery document", your code just works. Incredible. Thanks! If you ever need an idea for a second career, please consider giving Seaside/Ajax courses... Joachim
-- ----------------------------------------------------------------------- Objektfabrik Joachim Tuchel [hidden email] Fliederweg 1 http://www.objektfabrik.de D-71640 Ludwigsburg http://joachimtuchel.wordpress.com Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
Hey Joachim,
It you do “html jQuery document” instead of “html jQuery this”, you are attaching the handler to the document. Do you mean that this is needed in your case, or did it not work with “this” ? Because it should work with “html jQuery this” if all your items are below that orderedList The missing bracket is indeed the result of programming in the mail app :) cheers Johan
_______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
Johan
Am 11.02.17 um 15:13 schrieb Johan Brichau: > Hey Joachim, > > It you do “html jQuery document” instead of “html jQuery this”, you > are attaching the handler to the document. > Do you mean that this is needed in your case, or did it not work with > “this” ? > Because it should work with “html jQuery this” if all your items are > below that orderedList > it doesn't work with this, I need to attach the handler to the document. But that's fine ;-) > The missing bracket is indeed the result of programming in the mail app :) > Nevermind. Joachim (happy) -- ----------------------------------------------------------------------- Objektfabrik Joachim Tuchel mailto:[hidden email] Fliederweg 1 http://www.objektfabrik.de D-71640 Ludwigsburg http://joachimtuchel.wordpress.com Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1 _______________________________________________ seaside mailing list [hidden email] http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside |
Free forum by Nabble | Edit this page |