PDA

View Full Version : [CLOSED] UserControlRendererConfig RenderModes



michaeld
Dec 12, 2013, 11:57 PM
I've found that UserControlRenderConfig.RenderModes do the following:

Replace - replaces the parent control with the added control
AddTo/InsertTo - replaces the parent's child with the new usercontrol


But there is no way to AppendTo or InsertWithin. The client may already have added a control or two on the client-side, but these will get overwritten with AddTo or InsertTo (because the server doesn't have access to these items). I should be able to click a button, and add an unlimited number of new controls to the client without replacing the ones on the client already present.

Baidaly
Dec 13, 2013, 2:39 AM
Hello!

According to description of this RenderModes:

AddTo - Add the control to items collection of the element

InsertTo - Insert the control to items collection of the element

But I guess you mean that you want to append the control to the same container?

michaeld
Dec 13, 2013, 3:26 AM
According to description of this RenderModes:
AddTo - Add the control to items collection of the element
InsertTo - Insert the control to items collection of the element

Unless in my sample testing I did something wrong, my descriptions are more accurate based on the results I found. AddTo/InsertTo can insert an item to the parent's existing items (around other children discovered in the control list on the server which may not match the client), but it will overwrite the same previous render of the requested add if I added that user control already. It will not position a new control into the client's list of controls.


But I guess you mean that you want to append the control to the same container?
Yes. The client position, not the server position.

Daniil
Dec 13, 2013, 11:41 AM
Hi everybody,

Well, InsertTo and AddTo modes don't replace the components, it actually inserts and adds them. But, it pre-destroys a component with the same client id if exists.

So, to render a new item, you have to provide a component with a unique id.

michaeld
Dec 13, 2013, 12:46 PM
Well, InsertTo and AddTo modes don't replace the components, it actually inserts and adds them. But, it pre-destroys a component with the same client id if exists.

So, torender a new item, you have to provide a component with a unique id.

I considered and already tested this possibility and I got the same result. I've retested as well. The reason it is destroyed every time is it's pre-destroying the container each time. You can't change the name of the container.



public static int i = 1;
protected void OnLoad( object sender, DirectEventArgs e ) {
UserControlRendererConfig cfg = new UserControlRendererConfig {
UserControlPath = "Test42.ascx",
UserControlId = "uc"+i++.ToString(),
UserControlClientIDMode = System.Web.UI.ClientIDMode.Static,
Mode = RenderMode.AddTo,
Element = P.ClientID
};
UserControlRenderer.Render( cfg );
}

Baidaly
Dec 13, 2013, 8:52 PM
Could you provide a full sample, so we can avoid misunderstanding and discuss a real case.

If there is some issues we'd be glad to investigate them.

michaeld
Dec 14, 2013, 12:25 AM
Could you provide a full sample, so we can avoid misunderstanding and discuss a real case.

If there is some issues we'd be glad to investigate them.

aspx


<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load( object sender, EventArgs e ) {
}
public static int i = 1;
protected void OnLoad( object sender, DirectEventArgs e ) {
// Render the New Account Ask Question
//(new UserControlLoader() { Path = "Test42.ascx", UserControlID="uc" }).Render();
UserControlRendererConfig cfg = new UserControlRendererConfig {
UserControlPath = "Test42.ascx",
UserControlId = "uc"+i++.ToString(),
UserControlClientIDMode = System.Web.UI.ClientIDMode.Static,
Mode = RenderMode.AddTo,
Element = P.ClientID
};
UserControlRenderer.Render( cfg );
}
</script>


<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<title>Test42</title>
</head>
<body>
<form id="Form1" runat="server">
<ext:ResourceManager ID="ResourceManager1" runat="server" ScriptMode="Debug" SourceFormatting="true" RenderScripts="CDN" RenderStyles="CDN" />


<ext:Viewport ID="vp" runat="server" Layout="VBoxLayout">
<LayoutConfig>
<ext:VBoxLayoutConfig Align="Stretch" />
</LayoutConfig>
<Items>


<ext:Panel Title="Test" />
<ext:Panel ID="P" runat="server" Border="false" Padding="3" Flex="1" Title="Test42" Layout="VBoxLayout">
<LayoutConfig>
<ext:VBoxLayoutConfig Align="Stretch" />
</LayoutConfig>
<Items>
<ext:Button ID="Test" runat="server" Text="Test" OnDirectClick="OnLoad" />
</Items>
</ext:Panel>


</Items>
</ext:Viewport>
</form>
</body>
</html>

ascx


<%@ Control Language="C#" ClassName="Test42" %>
<script runat="server">
public static int i = 1;
protected void Page_Load( object sender, EventArgs e ) {
Button1.Text = i++.ToString();
}
protected void OnClick( object sender, DirectEventArgs e ) {
X.Msg.Alert( "Test", "Test1" );
}
</script>
<ext:Label ID="Label1" runat="server" Html="Inner" IDMode="Explicit" />
<ext:DatePicker ID="Dates" runat="server" IDMode="Explicit" />
<ext:Button ID="Button1" runat="server" Text="" OnDirectClick="OnClick" IDMode="Explicit" />




Click Test button multiple times. Even with the id name changing, you'll notice it still destroys the original and recreates.

michaeld
Dec 14, 2013, 12:37 AM
..........

Baidaly
Dec 14, 2013, 4:18 AM
Thank you for your example!

OK, the problem here is that you use wrong UserControlClientIDMode. And if you take a look what JS code is produced by the DirectEvent you can see that the container for the items of the UserControl are the same, therefore new items replace the old items.


// First call
{script:"Ext.net.append(Ext.getBody(),[\"<div id=\\\"uc1_ct_Content\\\" class=\\\"x-hidden\\\"><div id=\\\"App.Label1_Container\\\" style=\\\"display:inline;\\\"></div>\",\" <div id=\\\"App.Dates_Container\\\"></div>\",\" <div id=\\\"App.Button1_Container\\\"></div></div>\"].join(''));

Ext.net.ResourceMgr.destroyCmp(\"App.uc1_ct\");Ext.create(\"Ext.net.Label\",{id:\"Label1\",html:\"Inner\",renderTo:\"App.Label1_Container\"});Ext.create(\"Ext.picker.Date\",{id:\"Dates\",renderTo:\"App.Dates_Container\",format:\"d.m.Y\",longDayFormat:\"j F Y 'г.'\"});Ext.create(\"Ext.button.Button\",{id:\"Button1\",renderTo:\"App.Button1_Container\",text:\"1\",directEvents:{click:{fn:function(item,e){Ext.net. directRequest({control:this});}}}});App.P.add({id: \"uc1_ct\",xtype:\"container\",contentEl:\"uc1_ct_Content\"});"}

// Second call
{script:"Ext.net.append(Ext.getBody(),[\"<div id=\\\"uc2_ct_Content\\\" class=\\\"x-hidden\\\"><div id=\\\"App.Label1_Container\\\" style=\\\"display:inline;\\\"></div>\",\" <div id=\\\"App.Dates_Container\\\"></div>\",\" <div id=\\\"App.Button1_Container\\\"></div></div>\"].join(''));

Ext.net.ResourceMgr.destroyCmp(\"App.uc2_ct\");Ext.create(\"Ext.net.Label\",{id:\"Label1\",html:\"Inner\",renderTo:\"App.Label1_Container\"});Ext.create(\"Ext.picker.Date\",{id:\"Dates\",renderTo:\"App.Dates_Container\",format:\"d.m.Y\",longDayFormat:\"j F Y 'г.'\"});Ext.create(\"Ext.button.Button\",{id:\"Button1\",renderTo:\"App.Button1_Container\",text:\"2\",directEvents:{click:{fn:function(item,e){Ext.net. directRequest({control:this});}}}});App.P.add({id: \"uc2_ct\",xtype:\"container\",contentEl:\"uc2_ct_Content\"});"}

So just don't use ClientIDMode.Static:


UserControlRendererConfig cfg = new UserControlRendererConfig {
UserControlPath = "MyUserControl.ascx",
UserControlId = "uc"+i++.ToString(),
//UserControlClientIDMode = System.Web.UI.ClientIDMode.Static,
Mode = RenderMode.AddTo,
Element = P.ClientID,
ClearContainer = false
};

michaeld
Dec 16, 2013, 7:39 AM
Okay, thank you.

michaeld
Dec 16, 2013, 9:03 AM
Still your solution puts me back to the problem I'm having here:
http://forums.ext.net/showthread.php?27438-UserControlRendererConfig-does-not-render-some-controls


The bug in the above thread is preventing reliable use of Predictable. It's been a roadblock for about a week. See the sample posted at #10...

Baidaly
Dec 17, 2013, 1:04 AM
Yes, this roadblock is very strange.


Currently, to fix your test case you can set up IDMode="Legacy" or IDMode="Explicit" for the EventP.

However, I see that Daniil already suggested to change it to Legacy or Explicit. Does it help in your case?

michaeld
Dec 17, 2013, 4:36 AM
However, I see that Daniil already suggested to change it to Legacy or Explicit. Does it help in your case?

Well in this example case, UserControlRenderConfig uses ClientIDMode which has only Auto, Inherit, Predictable, and Static, so in this case, to answer your question, it will not.

Still you can close this thread because it is about RenderModes. At least now I understand that static will replace the existing control because of the nature upon which Static IDs in a UserControl will not change without manual tweaking all IDs in the UserControl's Page_Load as rendered with this model. Static cannot work as an option if you wish to repeat same control AddTo/InsertTo, and Predictable will not work until the fix has been applied. Fortunately I expect the need for repeating UserControls on the same Page this will be rare.

I know you guys are here to provide support and solutions, of course, and typically offering a work-around will get things up-and-working for most of your extnet developers. However, right now, I'm in the process of trying to extend ext.net to reliably allow a natural and reliable single-way to create UserControls in DirectEvents and that has not gone very well this past week. The subtle issues with IDModes which historically presented solutions are now actually the cause of the issues I'm having such that I have to consider very closely the impacts some of the decisions the toolset has that grant access to DirectMethods and DirectEvents during post-back.

Static IDs are great for client-side access (eg. App.direct.method(...)) but prohibitive for reusing the same UserControl on the same page. Also impacted is when they have their own DirectEvents. With the fix Daniil has promised in the other thread, I can return to using Predictable.

I've moved to exclusively using UserControlRenderConfig because it seems like the only implementation that seems to not replace the parent control content as well, which is critical if you have input fields with data expected not to be overwritten on the client. This is why I'm pushing harder to have improvements working in all IDModes.

However, I stopped researching to see if AddTo()/InsertTo() could do the same after running into a number of problems with it not handling the variations of UserControls, items/content, etc. I may try again if the UserControlRenderConfig doesn't prove versatile enough. I expect more problems ahead as I experiment with FormPanels with TrackResetOnLoad=true, but I can only move ahead with advanced features one-at-a-time after you fix each short-coming I run into. Baby-steps.

Baidaly
Dec 17, 2013, 9:39 PM
Yes, sometimes expected scenarios don't meet real-life scenarios.

We are closing this thread for now but feel free to update it or ask questions.

Daniil
Dec 18, 2013, 4:05 AM
Thank you for the feedback. It is very valuable for us.

Btw, you might be interested to read this thread. It seems to be related to what you are doing.
http://forums.ext.net/showthread.php?25279

geoffrey.mcgill
Dec 18, 2013, 4:53 AM
The following is not directly related to this problem, but might be helpful to someone researching this topic.

http://forums.ext.net/showthread.php?27611-Triggering-DirectMethod-in-a-UserControl

michaeld
Dec 18, 2013, 12:35 PM
Thank you for the feedback. It is very valuable for us.

Btw, you might be interested to read this thread. It seems to be related to what you are doing.
http://forums.ext.net/showthread.php?25279

Yes, it's good to know I am not the only one. I don't like his implementation at all though. I see major security issues in not encrypting his control names and I don't see how he handles reload if the control he's adding also has its own DirectEvents/DirectMethods. Honestly, I've already got a better solution I'm testing now that is working pretty well and is based entirely on the feature request I placed here: http://forums.ext.net/showthread.php?27574-UserControl-Auto-Loader-amp-Manager. Between the two of us, I think we've made a case this should be implemented in extnet.

The only reason I haven't posted my implementation so far is 1) I'm waiting for you guys to fix the limitation here: https://github.com/extnet/Ext.NET/issues/403 [I've presently changed my local branch of ext.net from creating the container Static to Inherit and that seems to be sufficient for now], and 2) I was considering testing more samples before posting my solution. However, I'm reconsidering just starting a new thread and we can all watch the progress.



The following is not directly related to this problem, but might be helpful to someone researching this topic.

http://forums.ext.net/showthread.php?27611-Triggering-DirectMethod-in-a-UserControl

Yes, thank you, geoffrey. I'm already aware of #{DirectMethods} token as a way to gain access to the method of a predictable idmode DirectMethod in a usercontrol. This requires a transformation, but it works, and yes, someone might find this insight useful.

michaeld
Dec 18, 2013, 3:06 PM
As promised...
http://forums.ext.net/showthread.php?27618-Add-UserControls-in-DirectEvents-Methods-and-have-them-automatically-Reload-on-Post-back-through-messanging-in-Hidden-Fields&p=122873#post122873