[ 
https://issues.apache.org/jira/browse/WICKET-6987?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

leclerc cyril updated WICKET-6987:
----------------------------------
     Attachment: image-2022-06-02-09-01-25-801.png
                 image-2022-06-02-08-57-50-406.png
    Description: 
In a page (extends {*}webPage{*}) when we replace a component in a panel with 
_panel.replace_ or {_}panel.addOrReplace{_}, when it remove the old component, 
the method detach is called and will detach the parent model instead of it own 
model if present. it cause a reload of the model when the new composant is 
added.

So imagine you have a panel with 20 components using 1 detachablemodel (wit 
some db queries),  and on submit or on action we want to add all components in 
panel (loaded by a class), all are using the same model loaded once on the 
first *_getModel_* call , then all components will use same model value, and 
then detach is called => ok

 

But if we have a button will submit a form, and we create new components and 
replace in our panel, on each replace method, the remove method will detach 
parent model, so then on each component it will load the model (so 20x load 
model called)

 

How to reproduce ?

take a helloworld projet, create a panel with one component Label using a 
detachable string model

in HomePage constructor set panel, then first add the component, then replace 
it then make something else (getObject for example), on replace method model in 
page will be detached and we have to reload it

 
{code:java}
public class HomePage extends WebPage {
   private static final long serialVersionUID = 1L;


   Panel panel ;

   IModel<String> model = new LoadableDetachableModel<String>() {
      @Override
      protected String load() {
         return "test";
      }
      @Override
      protected void onDetach() {
         super.onDetach();
      }
   };

   public HomePage(final PageParameters parameters) {
      super(parameters);
      model.getObject();
      add(new Label("version", 
getApplication().getFrameworkSettings().getVersion()));
      panel = new HomePanel( "homePanel");
      //first time no problem
      panel.addOrReplace(  new Label( "test", model ) );
      add(panel);
      //use ame model loaded
      model.getObject();
      //here will detach the model
      panel.addOrReplace(  new Label( "test", model ) );
      //load a new model
      model.getObject();

   }

}
 {code}
and in panel
{code:java}
public class HomePanel extends Panel { Label label; public HomePanel(String id) 
{ super( id ); } public HomePanel(String id, IModel<String> model) { super( id, 
model ); label = new Label( "test", model.getObject() ); add( label ); } }
{code}
in home page html set the panel
{code:java}
<span wicket:id="homePanel"> </span>
{code}
in panel html
{code:java}
<wicket:panel xmlns:wicket="http://wicket.apache.org";>
   User:        <span wicket:id="test">dummy name</span><br/>
</wicket:panel> {code}
to go further on getModelImpl() (in component.java) we retrieve the first 
element in data object in the picture below we make the detach on the HomePanel 
Object replaced but we see the model detach it the page model

!image-2022-06-02-08-57-50-406.png!

 

so why we detach the parent model instead of just let the page do this job ?

 

!image-2022-06-02-09-01-25-801.png!

  was:
In a page (extends {*}webPage{*}) when we replace a component in a panel, and 
when it remove the old component, the method detach will detach the parent 
model instead of it own model if present. it cause a reload of the model when 
the new composant is added.

So imagine you have a panel with 20 components using 1 detachablemodel (wit 
some db queries), all use the same model loaded once on the first *_getModel_* 
call , then all components will use same model value, and then detach is called 
=> ok

 

But if we have a button will submit a form, and we create new components and 
replace in our panel, on each replace method, the remove method will detach 
parent model, so then on each component it will load the model (so 20x load 
model called)

 

How to reproduce ?

take a helloworld projet, create a panel with one component Label using a 
detachable string model

in HomePage constructor set panel

add a form et onsubmit replace the panel (1 or N time you want) with the same 
component

 
{code:java}
public class HomePage extends WebPage {
   private static final long serialVersionUID = 1L;


   Panel panel ;

   IModel<String> formModel = Model.of("");

   IModel<String> model = new LoadableDetachableModel<String>() {
      @Override
      protected String load() {
         return formModel.getObject();
      }
      @Override
      protected void onDetach() {
         super.onDetach();
      }
   };

   public HomePage(final PageParameters parameters) {
      super(parameters);
      final var form = new Form<>( "form" ){
         @Override
         protected void onSubmit(){
            System.out.println("submitted");
            panel.replace( new Label( "test", model ) );
         }
      };
      add( form );
      form.add(new TextField("field", formModel  ) );
      form.add( new Label( "result", model) );
      form.add(new Label("version", 
getApplication().getFrameworkSettings().getVersion()));
      panel = new HomePanel( "homePanel");
      panel.add( new Label( "test", model) );
      form.add(panel);
   }
   
}  {code}
and in panel
{code:java}
public class HomePanel extends Panel { Label label; public HomePanel(String id) 
{ super( id ); } public HomePanel(String id, IModel<String> model) { super( id, 
model ); label = new Label( "test", model.getObject() ); add( label ); } }
{code}
in home page html
{code:java}
<input type="text" wicket:id="field">
<div class="col-12"><button type="submit" class="btn btn-primary"><i class="fas 
fa-sync">SUBMIT</i></button></div>
Result:        <span wicket:id="result">dummy name</span><br/> {code}
in panel html
{code:java}
<wicket:panel xmlns:wicket="http://wicket.apache.org";>
   User:        <span wicket:id="test">dummy name</span><br/>
</wicket:panel> {code}
to go further on getModelImpl() (in component.java) we retrieve the first 
element in data object:
{code:java}
IModel<?> getModelImpl()
{
   if (getFlag(FLAG_MODEL_SET))
   {
      return (IModel<?>)data_get(0); (this causing detach of the parent page 
model)
   }
   return null;
} {code}


> Panel replace method detach parent model
> ----------------------------------------
>
>                 Key: WICKET-6987
>                 URL: https://issues.apache.org/jira/browse/WICKET-6987
>             Project: Wicket
>          Issue Type: Bug
>          Components: wicket
>    Affects Versions: 9.10.0
>            Reporter: leclerc cyril
>            Priority: Major
>         Attachments: image-2022-06-02-08-57-50-406.png, 
> image-2022-06-02-09-01-25-801.png
>
>
> In a page (extends {*}webPage{*}) when we replace a component in a panel with 
> _panel.replace_ or {_}panel.addOrReplace{_}, when it remove the old 
> component, the method detach is called and will detach the parent model 
> instead of it own model if present. it cause a reload of the model when the 
> new composant is added.
> So imagine you have a panel with 20 components using 1 detachablemodel (wit 
> some db queries),  and on submit or on action we want to add all components 
> in panel (loaded by a class), all are using the same model loaded once on the 
> first *_getModel_* call , then all components will use same model value, and 
> then detach is called => ok
>  
> But if we have a button will submit a form, and we create new components and 
> replace in our panel, on each replace method, the remove method will detach 
> parent model, so then on each component it will load the model (so 20x load 
> model called)
>  
> How to reproduce ?
> take a helloworld projet, create a panel with one component Label using a 
> detachable string model
> in HomePage constructor set panel, then first add the component, then replace 
> it then make something else (getObject for example), on replace method model 
> in page will be detached and we have to reload it
>  
> {code:java}
> public class HomePage extends WebPage {
>    private static final long serialVersionUID = 1L;
>    Panel panel ;
>    IModel<String> model = new LoadableDetachableModel<String>() {
>       @Override
>       protected String load() {
>          return "test";
>       }
>       @Override
>       protected void onDetach() {
>          super.onDetach();
>       }
>    };
>    public HomePage(final PageParameters parameters) {
>       super(parameters);
>       model.getObject();
>       add(new Label("version", 
> getApplication().getFrameworkSettings().getVersion()));
>       panel = new HomePanel( "homePanel");
>       //first time no problem
>       panel.addOrReplace(  new Label( "test", model ) );
>       add(panel);
>       //use ame model loaded
>       model.getObject();
>       //here will detach the model
>       panel.addOrReplace(  new Label( "test", model ) );
>       //load a new model
>       model.getObject();
>    }
> }
>  {code}
> and in panel
> {code:java}
> public class HomePanel extends Panel { Label label; public HomePanel(String 
> id) { super( id ); } public HomePanel(String id, IModel<String> model) { 
> super( id, model ); label = new Label( "test", model.getObject() ); add( 
> label ); } }
> {code}
> in home page html set the panel
> {code:java}
> <span wicket:id="homePanel"> </span>
> {code}
> in panel html
> {code:java}
> <wicket:panel xmlns:wicket="http://wicket.apache.org";>
>    User:        <span wicket:id="test">dummy name</span><br/>
> </wicket:panel> {code}
> to go further on getModelImpl() (in component.java) we retrieve the first 
> element in data object in the picture below we make the detach on the 
> HomePanel Object replaced but we see the model detach it the page model
> !image-2022-06-02-08-57-50-406.png!
>  
> so why we detach the parent model instead of just let the page do this job ?
>  
> !image-2022-06-02-09-01-25-801.png!



--
This message was sent by Atlassian Jira
(v8.20.7#820007)

Reply via email to