Ajax delete component only works if #children still report all previously deleted components?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Ajax delete component only works if #children still report all previously deleted components?

Sophie424
I can get a consistent WAComponentsNotFound failure in the attached minimal
component C. Here I am #deleting components, following up on some things
posted on an earlier thread.

To break: Run it at localhost://..../c. 'Add' a few nested components, then
try several 'removes'.

To fix: remove the commented code in #children. In other words, if #children
always reports all components ever rendered including those deleted, the
failure does not occur. (Elsewhere in my fuller app I tried keeping just the
last deleted component, hoping that would suffice between the calls to
#children and #render, but it did not).

If this slow progress on my part reflects my slow understanding of how to
use Seaside + SU, my apologies ... I have just not been able to figure it
out by stepping through the debugger and inspecting the various
continuations and renderingContexts. Hope my difficulties help someone
else...

I am really hoping to find some 2.8 work-around, as I have already convinced
others to follow this path to Ajax :-(

Longer term would this be helped by a clearer separation of different Ajax
callbacks phases for (a) domain model update, then (b) component tree update
+ re-rendering?

As always, thanks.

Sophie


begin 666 C.st
M)T9R;VT@4W%U96%K,RXY(&]F(#<@3F]V96UB97(@,C P-B!;;&%T97-T('5P
M9&%T93H@(S<P-C==(&]N(#$V($9E8G)U87)Y(#(P,#@@870@,3$Z,S(Z,C0@
M<&TG(0U704-O;7!O;F5N="!S=6)C;&%S<SH@(T,-"6EN<W1A;F-E5F%R:6%B
M;&5.86UE<SH@)VED('-U8G,@<&%R96YT(&1E;&5T960G#0EC;&%S<U9A<FEA
M8FQE3F%M97,Z("<G#0EP;V]L1&EC=&EO;F%R:65S.B G)PT)8V%T96=O<GDZ
M("=-07 M5')Y:6YG+4%J87@G(0T-(4,@;65T:&]D<T9O<CH@)V%S('EE="!U
M;F-L87-S:69I960G('-T86UP.B G<VD@,B\Q-B\R,# X(#(S.C(X)R$-8F%S
M:6-296YD97)/;CH@:'1M;" -"6AT;6P@<&%R86=R87!H.B G;VYE($,G+@T)
M:'1M;"!A;F-H;W(-"0EO;D-L:6-K.B H:'1M;"!U<&1A=&5R#0D)"0EI9#H@
M:60@.PT)"0D)8V%L;&)A8VLZ( T)"0D)"5L@.B!R('P@#0D)"0D)<V5L9B!S
M=6)S(&%D9#H@*$,@;F5W('!A<F5N=#H@<V5L9BDN#0D)"0D)<V5L9B!B87-I
M8U)E;F1E<D]N.B!R(%TI(#L-"0EW:71H.B G861D)RX-"6AT;6P@<W!A8V4Z
M(#(N#0EH=&UL(&%N8VAO<@T)"6]N0VQI8VLZ("AH=&UL('5P9&%T97(-"0D)
M"6ED.B H<&%R96YT( T)"0D)"0EI9DYO=$YI;#H@6R!P87)E;G0@:60@70T)
M"0D)"0EI9DYI;#H@6R G,"<@72D@.PT)"0D)8V%L;&)A8VLZ( T)"0D)"5L@
M.B!R('P@#0D)"0D)<&%R96YT('-U8G,@<F5M;W9E.B!S96QF+@T)"0D)"7!A
M<F5N="!D96QE=&5D(&%D9#H@<V5L9BX-"0D)"0EP87)E;G0@8F%S:6-296YD
M97)/;CH@<B!=*2 [#0D)=VET:#H@)W)E;6]V92<N#0ES=6)S(&1O.B!;(#H@
M96$@?"!H=&UL(')E;F1E<CH@96$@72$@(0T-(4,@;65T:&]D<T9O<CH@)V%S
M('EE="!U;F-L87-S:69I960G('-T86UP.B G<VD@,B\Q-B\R,# X(#(S.C(X
M)R$-8VAI;&1R96X-"5X@<W5B<R!C;W!Y#0D)(F%D9$%L;#H@9&5L971E9" [
M#0D)>6]U<G-E;&8B(2 A#0TA0R!M971H;V1S1F]R.B G87,@>65T('5N8VQA
M<W-I9FEE9"<@<W1A;7 Z("=S:2 R+S$V+S(P,#@@,C,Z,C@G(0UD96QE=&5D
M#0E>(&1E;&5T960A("$-#2%#(&UE=&AO9'-&;W(Z("=A<R!Y970@=6YC;&%S
M<VEF:65D)R!S=&%M<#H@)W-I(#(O,38O,C P." R,CHU,B<A#6ED#0E>(&ED
M(2 A#0TA0R!M971H;V1S1F]R.B G87,@>65T('5N8VQA<W-I9FEE9"<@<W1A
M;7 Z("=S:2 R+S$V+S(P,#@@,C,Z,#$G(0UI;FET:6%L:7IE#0ES=7!E<B!I
M;FET:6%L:7IE+@T)<W5B<R Z/2!/<F1E<F5D0V]L;&5C=&EO;B!N97<N#0ED
M96QE=&5D(#H]($]R9&5R961#;VQL96-T:6]N(&YE=RXA("$-#2%#(&UE=&AO
M9'-&;W(Z("=A<R!Y970@=6YC;&%S<VEF:65D)R!S=&%M<#H@)W-I(#(O,38O
M,C P." R,CHT,R<A#7!A<F5N=#H@8PT)<&%R96YT(#H](&,A("$-#2%#(&UE
M=&AO9'-&;W(Z("=A<R!Y970@=6YC;&%S<VEF:65D)R!S=&%M<#H@)W-I(#(O
M,38O,C P." R,SHR-R<A#7)E;F1E<D-O;G1E;G1/;CH@:'1M; T):'1M;"!D
M:78-"0EI9#H@*&ED(#H](&AT;6P@;F5X=$ED*3L-"0EW:71H.B!;<V5L9B!B
M87-I8U)E;F1E<D]N.B!H=&UL72$@(0T-(4,@;65T:&]D<T9O<CH@)V%S('EE
M="!U;F-L87-S:69I960G('-T86UP.B G<VD@,B\Q-B\R,# X(#(R.C4R)R$-
M<W1Y;&4-"5X@)R!D:78@>R!M87)G:6XZ(#%E;3L@8F]R9&5R.B Q<'0@<V]L
M:60@8FQA8VL[('TG(2 A#0TA0R!M971H;V1S1F]R.B G87,@>65T('5N8VQA
M<W-I9FEE9"<@<W1A;7 Z("=S:2 Q+S$X+S(P,#@@,3@Z,S0G(0US=6)S#0E>
M('-U8G,A("$-#2(M+2 M+2 M+2 M+2 M+2 M+2 M+2 M+2 M+2 M+2 M+2 M
M+2 M+2 M+2 M+2 M+2 M+2 M+2 B(0T-0R!C;&%S<PT):6YS=&%N8V5687)I
M86)L94YA;65S.B G)R$-#2%#(&-L87-S(&UE=&AO9'-&;W(Z("=A<R!Y970@
M=6YC;&%S<VEF:65D)R!S=&%M<#H@)W-I(#$O,3@O,C P." Q.#HS-"<A#6-A
M;D)E4F]O= T)7B!T<G5E(2 A#0TA0R!C;&%S<R!M971H;V1S1F]R.B G87,@
M>65T('5N8VQA<W-I9FEE9"<@<W1A;7 Z("=S:2 R+S$V+S(P,#@@,C(Z-#8G
M(0UI;FET:6%L:7IE#0E\(&%P<"!\#0EA<' @.CT@<V5L9B!R96=I<W1E<D%S
M07!P;&EC871I;VXZ("-C+@T)87!P(&%D9$QI8G)A<GDZ(%-53&EB<F%R>2X-
5"2$@(0T-#4,@:6YI=&EA;&EZ92$-
`
end


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Ajax delete component only works if #children still report all previously deleted components?

Lukas Renggli
Again this is exactly the same problem as we have seen before:

- Callbacks have an owner, that is set when defining the components.
When you directly call an internal rendering method of a different
component (and you do this in your updater) you violate this contract
(see the class comment of WAComponent).
- Callbacks for a particular owner are only processed if the owner is
in the component tree.

As I already said many times: If you want to have it easy, don't mix
components and AJAX. In your code for example, the subclass C doesn't
use any functionality of its superclass WAComponent (with the
exception that it can be registered as root).

Otherwise you might want try adding the following method:

WARenderCanvas>>in: aComponent do: aBlock
        | previous |
        previous := callbacks.
        callbacks := context callbacksFor: aComponent.
        self render: aBlock.
        callbacks := previous

Then change all your rendering code from AJAX callbacks to something along:

        callback: [ : r |
                self subs add: (C new parent: self).
                r in: self do: [ self basicRenderOn: r ] ]) ;

and

        callback: [ : r |
                parent subs remove: self.
                parent deleted add: self.
                r in: parent do: [ parent basicRenderOn: r ] ]) ;

> Longer term would this be helped by a clearer separation of different Ajax
> callbacks phases for (a) domain model update, then (b) component tree update
> + re-rendering?

There is just one AJAX callback phase.

Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Ajax delete component only works if #children stillreport all previously deleted components?

Sophie424
"Lukas Renggli" <[hidden email]> wrote in message

> (see the class comment of WAComponent).

Sorry, I had misunderstood the wording of that comment and assumed the
callbacks were a separate thing from the rendering itself.

> Otherwise you might want try adding the following method:

That worked. In fact, it seems to not even require holding on to deleted
components.

callback: [ : r |
  parent subs remove: self.
  "parent deleted add: self. -- NOT needed"
  r in: parent do: [ parent basicRenderOn: r ] ]) ;

Is that what you expect? That would be great news to me!

I am using the non-component option where I can.

Sincere thanks for your help (& patience),

Sophie



_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Ajax delete component only works if #children stillreport all previously deleted components?

Lukas Renggli
> callback: [ : r |
>   parent subs remove: self.
>   "parent deleted add: self. -- NOT needed"
>   r in: parent do: [ parent basicRenderOn: r ] ]) ;
>
> Is that what you expect? That would be great news to me!

Yes, exactly. The #in:do: implementation is what I mentioned in one of
the last mails. As you can see the #in:do: just changes the owner of
the callbacks while executing the block.

It is not nice, but it should work in all situations where you call
internal rendering methods of different components. We will try to
find a better solution for Seaside 2.9.

Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Ajax delete component only works if #childrenstillreport all previously deleted components?

Sophie424
"Lukas Renggli" <[hidden email]> wrote in message

> It is not nice,

Oh, you have no idea how lovely it looks to me :-)

> but it should work in all situations where you call
> internal rendering methods of different components.

Great. I was trying to figure out why I need to use #in:do: even for a
self-call:
 callback: [:r |
    self subs add: (C new parent: self).
    r in: self do: [self basicRenderOn: r] ]

My interpretations are 1 & 2 below:

1. If an Ajax callback changes self's component tree in a way which
invalidates the last call to #children, use
   r in: self do: [self reRenderOn... r].
This ensures that all re-rendered callbacks have the right owner.

2. Anytime you call internal rendering methods of different components
  (e.g. via other Component renderXYZOn: r)
in an Ajax callback, use #in:do: to get correct ownership of re-rendered
callbacks.

Thanks - Sophie



_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Ajax delete component only works if #childrenstillreport all previously deleted components?

Lukas Renggli
> Great. I was trying to figure out why I need to use #in:do: even for a
> self-call:
>  callback: [:r |
>     self subs add: (C new parent: self).
>     r in: self do: [self basicRenderOn: r] ]

Heh, I was wondering about that one as well.

For all AJAX callbacks the html-render-canvas from the last full
refresh is reused. This is conceptually wrong, it should only reuse
the callback-registry. Furthermore that's also the reason why it
mostly works if you accidently use the renderer from a different
scope.

Anyway, the render-canvas remembers the last component rendered fully
and from then on uses this component until you do another full render
of a different component. In you code you have a great mixture of
different components rendering each other partly and fully.

We are working on a solution for Seaside 2.9 that makes all these
things go away.

Cheers,
Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Ajax delete component only works if#childrenstillreport all previously deleted components?

Sophie424
"Lukas Renggli" <[hidden email]> wrote in message

> For all AJAX callbacks the html-render-canvas from the last full
> refresh is reused. This is conceptually wrong, it should only reuse
> the callback-registry.

That was the first thing that got my attention in Michael Lucas-Smith's
recent post in the "mootools" thread. (btw, I think your perspective on his
points would be quite insightful).

> Anyway, the render-canvas remembers the last component rendered fully

The root component? Leaf? Via canvas render: aComp?

(Please ignore if this is too hard to explain, or if I'm too slow, or if you
are just about to post that sequence diagram from your new book draft :-)
... I've tried the debugger and the fog thinned ever so slightly :-)

> and from then on uses this component

"Uses" it to processCallbackStream? processChildCallbacks? For any callback
on any part of the tree? To start collecting #children?

> We are working on a solution for Seaside 2.9 that makes all these
> things go away.

Looking forward to 2.9! Any idea if it might include back-button for Ajax,
or a javascript decoupled from Prototype/SU framework?

Thank you!

Sophie



_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Re: Ajax delete component only works if#childrenstillreport all previously deleted components?

Lukas Renggli
> > For all AJAX callbacks the html-render-canvas from the last full
> > refresh is reused. This is conceptually wrong, it should only reuse
> > the callback-registry.
>
> That was the first thing that got my attention in Michael Lucas-Smith's
> recent post in the "mootools" thread. (btw, I think your perspective on his
> points would be quite insightful).

I don't exactly see what part you are referring too.

> > Anyway, the render-canvas remembers the last component rendered fully
>
> The root component? Leaf? Via canvas render: aComp?

Last time you did call #render: with a component as argument.

> > and from then on uses this component
>
> "Uses" it to processCallbackStream? processChildCallbacks? For any callback
> on any part of the tree? To start collecting #children?

It uses this component as the owner (which is presumably wrong) of the
callbacks in partial render passes that follow.

> > We are working on a solution for Seaside 2.9 that makes all these
> > things go away.
>
> Looking forward to 2.9! Any idea if it might include back-button for Ajax,
> or a javascript decoupled from Prototype/SU framework?

Back-button: No

JavaScript decoupling: Yes, we are slowly working on that.

The question is, what would be useful for other frameworks?

Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Re: Ajax delete component only worksif#childrenstillreport all previously deleted components?

Sophie424
"Lukas Renggli" <[hidden email]> wrote in message

>> That was the first thing that got my attention in Michael Lucas-Smith's
>> recent post in the "mootools" thread. (btw, I think your perspective on
>> his
>> points would be quite insightful).
>
> I don't exactly see what part you are referring too.

Here it is, relating to render-canvas and callback-registry:

"f) Because there was only ever one page on the server to represent a
single user, there was rarely any memory concerns. There was also no
passes to process actions and callbacks, those were registered in to a
weak dictionary so that if an element was destroyed, so was the callback."

> It uses this component as the owner (which is presumably wrong) of the
> callbacks in partial render passes that follow.

I get it now, thank you. I guess it needs this owner to do things like find
the decorator-chain (assuming decorators get a shot at wrapping stuff around
callback executions).

> The question is, what would be useful for other frameworks?

Sebastian makes some good points on jQuery: I've been reading on it and
jQuery code reads really clean and succinct, it has no conflicts with
prototype (so incrementally using it is painless), it is nicely OO, cleanly
separates base library from plugins, very well documented (2+ books!), is on
the rise, and is getting *lots* of plugins http://plugins.jquery.com/ from
infrastructure (like AjaxQueue - serialize possible race-conditions) to rich
UI widgets.

It might be a good 2nd reference point from which to generalize.

Thank you again,

Sophie



_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

RE: Re: Re: Re: Re: Ajax delete component onlyworksif#childrenstillreport all previously deleted components?

Sebastian Sastre-2

> > The question is, what would be useful for other frameworks?
>
> Sebastian makes some good points on jQuery: I've been reading
> on it and
> jQuery code reads really clean and succinct, it has no conflicts with
> prototype (so incrementally using it is painless), it is
> nicely OO, cleanly
> separates base library from plugins, very well documented (2+
> books!), is on
> the rise, and is getting *lots* of plugins
> http://plugins.jquery.com/ from
> infrastructure (like AjaxQueue - serialize possible
> race-conditions) to rich
> UI widgets.
>
> It might be a good 2nd reference point from which to generalize.
>
> Thank you again,
>
> Sophie
>
Sorry to interrupt but here is a sorteable tree based on jQuery that works with
drag & drop:
http://www.bernardopadua.com/nestedSortables/test/nested_sortable/

I'm looking the plugins and they seems to have covered a wide spectrum of UI
problems quite appealing,

Cheers,

Sebastian

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside