To reiterate:
- RootPanel.detachOnWindowClose() must be called for all widgets that "have
no parents".
  - This is implicitly called by Widgets' wrap() methods and
RootPanel.get(id).
  - All widgets for which this method is called will remain marked as
'attached' until RootPanel.detachNow() is called.
- If a widget attached in this way has its element detached from the DOM,
implicitly or explicitly, you *must* call RootPanel.detachNow().
  - There is no way for GWT to know that you've done this, because the
browser doesn't provide this notification.
- If the assertion in RootPanel.detachWidgets() fails, that means that a
widget was found in the detach list that is *not* attached to the DOM. This
proves that the element was detached without its Widget being passed to
RootPanel.detachNow().

This code cannot realistically know about your DOM structure, so if you do
something like this:

<div id='outer'>
  <button id='inner'/>
</>

html = HTML.wrap(Document.get().getElementById("outer"));
button = Button.wrap(Document.get().getElementById("inner"));
html.setInnerHTML("Look, I just nuked the button widget!");

You still have to call detachNow() for the inner button widget. Despite the
fact that the outer HTML widget appears to contain the Button widget,
there's still no parent-child hierarchy at the widget level.

Honestly, I would prefer to assert up front that this sort of implicit
parent-child relationship among 'root' widgets not be created in the first
place, but that's pretty tricky, and I don't believe it could be resilient
to arbitrary DOM trickery anyway.

Cheers,
joel.

On Tue, Sep 23, 2008 at 10:32 AM, Ed <[EMAIL PROTECTED]> wrote:

>
> Thanks again for your answer.
>
> Let me see if I understand you completely.
>
> > If you are going to be removing existing RootPanels from the DOM
> implicitly
> > (i.e. by removing one of their parent elements), you're going to have to
> > call RootPanel.detachNow() on them.
>
> By removing you mean, physical removing it from the DOM without
> detaching it?
>
> Calling  "widget.onDetach()" is enough for overcoming this orphan
> problems?
>
> Is so, why does the assertion not take that into account? I mean, in
> my case I switch the original content for some other HTML widget,
> like:
> stuff.clear();
> stuff.add(otherWidget);
>
> In the clear() method it will remove the HTML widget that contains the
> RootPanels, such that it will properly detach all his children and as
> such the RootPanels. Shouldn't a RootPanel override the onDetach()
> method and then remove itself form the widgetsToDetach list? Isn't
> this what happens when calling RootPanel.detachNow(theRootPanel)? such
> that it can be automatically done in the onDetach() method in
> RootPanel.
>
> I think I am missing something :(.. Please some more details if
> possible, or a tinny example?
>
> I understand that a Widget should be attached to the Document body to
> be removed properly, but I don't understand the  Assertion. Even do
> you signal in the Assertion that he isn't attached to the Body, you
> are calling onDetach() anyway, so I would say it's not important
> anymore, he is properly detached anyway (just like what happens in
> RootPanel.detachNow() ), so what's the point of this Assertion? :(
>
> -- Ed
>
> On Sep 23, 3:33 pm, "Joel Webber" <[EMAIL PROTECTED]> wrote:
> > If you are going to be removing existing RootPanels from the DOM
> implicitly
> > (i.e. by removing one of their parent elements), you're going to have to
> > call RootPanel.detachNow() on them. The reason this is necessary is that
> > otherwise they will be "orphaned", meaning that they're out of the DOM,
> but
> > neither they nor their child widgets are aware of having been removed.
> This
> > can break a number of things, including potentially creating leaks.
> That's
> > also why the assertion in detachWidgets() is necessary -- I would prefer
> to
> > be able to throw an exception when the problem is created (i.e. when the
> > parent element is removed from the DOM), but there's no way to receive
> > notification of this.
> >
> > On Mon, Sep 22, 2008 at 4:57 PM, Ed <[EMAIL PROTECTED]> wrote:
> >
> > > He Joel,
> >
> > > Just a tinny problem I am still stuck with:
> > > In your example above, the replaced content, contains a few more
> > > RootPanels like this:
> > > ...>
> > >  <div id='stuff'>
> > >    <... stuff ...>
> > >     <div id='rootPanela'>
> > >      ....
> > >     <div id='rootPanelb'>
> > >  </div>
> > > <...>
> >
> > > What I do: replacing the content of id="stuff" with some HTML widget
> > > when the user presses a button, like you describe above. When the user
> > > clicks another button, I put back the original content.
> > > However, the original content contains some html snippets that are
> > > loaded with a RootPanel (for example to add some Form).
> > > If the user clicks a button such that the original content is
> > > replaced, such that the RootPanels are put aside and not attached to
> > > the body, the new code (I think it's even your code ;)) in RootPanel:
> > > detachWidgets will throw an Assert exception when the hosted browser
> > > is refreshed at that moment, as these Rootpanels aren't attached to
> > > the Body and the RootPanel will try to remove it when the window
> > > closes.
> >
> > > Any idea how to solve this?
> > > I could remove these RootPanels from the widgetsToDetach in the
> > > RootPanel when they are put aside, but I don't know the exact
> > > RootPanel beforehand and I don't like this solution as it avoids my
> > > code from being losely coupled...
> >
> > > Is this exception realy a possible memory leak? And might it not a bit
> > > too tight (the exception)
> >
>

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to