PDA

View Full Version : [CLOSED] Desktop module does not work when added dynamically



fotis
Sep 26, 2016, 2:31 PM
I have a problem with the modules that are added dynamically in Desktop. If they contain javascript code this is not added in the page. It is very easy to replicate in examples by adding the AccordionWindow dynamically.


[DirectMethod(ShowMask=true)]
public void AddNewModule()
{
Desktop.GetInstance().RemoveModule("add-module");
DesktopModuleProxy control = Ext.Net.Utilities.ControlUtils.FindControl<Ext.Net.DesktopModuleProxy>(this.LoadControl("modules/TabWindow.ascx"));
control.RegisterModule();

Desktop.GetInstance().RemoveModule("AccordionWindow");
DesktopModuleProxy control2 = Ext.Net.Utilities.ControlUtils.FindControl<Ext.Net.DesktopModuleProxy>(this.LoadControl("modules/AccordionWindow.ascx"));
control2.RegisterModule();

}




and remove line

<mod:AccordionWindow runat="server" />

You 'll get the error "Uncaught ReferenceError: mimicRemoteLoading is not defined" which is a js function inside the control.

Any workaround with this?

fabricio.murta
Sep 26, 2016, 7:24 PM
Hello!

In order to have dymamically added controls interpret their scripts, they have to be positioned somewhere inside the page, much like the accordion window is added in the original example.

So, you can create a placeholder container for easy reference from code behind and add and update the custom controls contents inside that container.

Please refer to this forum thread: Dynamic usercontrol and execute javascript (http://forums.ext.net/showthread.php?13936).

Hope this helps!

fotis
Sep 27, 2016, 10:17 AM
Hi Fabricio,

Unfortunately using a container does not seem to resolve this. Sending the full page to check. Maybe desktop interferes with the controls?


<%@ Page Language="C#" %>

<%@ Register Src="modules/AccordionWindow.ascx" TagPrefix="mod" TagName="AccordionWindow" %>
<%@ Register Src="modules/GridWindow.ascx" TagPrefix="mod" TagName="GridWindow" %>
<%@ Register Src="modules/SystemStatus.ascx" TagPrefix="mod" TagName="SystemStatus" %>


<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
// dynamic module loading via DesktopModuleProxy
this.LoadControl("modules/WhatsNew.ascx");
}
}


protected void Logout_Click(object sender, DirectEventArgs e)
{
// Logout from Authenticated Session
this.Response.Redirect("Default.aspx");
}


[DirectMethod(ShowMask = true)]
public void CreateWindow()
{
Desktop.GetInstance().CreateWindow(new Window
{
Title = "New window",
Width = 300,
Height = 300,
CloseAction = CloseAction.Destroy,
Html="The window is created"
});
}


[DirectMethod(ShowMask=true)]
public void AddNewModule()
{

Desktop.GetInstance().RemoveModule("AccordionWindow");
DesktopModuleProxy control2 = Ext.Net.Utilities.ControlUtils.FindControl<Ext.Net.DesktopModuleProxy>(this.LoadControl("modules/AccordionWindow.ascx"));
control2.RegisterModule();


modulescon.ContentControls.Add(control2);
modulescon.UpdateContent();

}


[DirectMethod(ShowMask = true)]
public void AddAnotherModule()
{
Desktop.GetInstance().RemoveModule("add1-module");
DesktopModule m = new DesktopModule
{
ModuleID = "dyn-mod",
Shortcut = new DesktopShortcut
{
Name = "Dynamic Module"
},


Launcher = new Ext.Net.MenuItem
{
Text = "Dynamic module"
},


Window =
{
new Window
{
Title = "Dynamic Window",
Width = 300,
Height = 300,
DefaultRenderTo = Ext.Net.DefaultRenderTo.Form,
Icon = Icon.ApplicationAdd
}
},


AutoRun = true
};



}
</script>


<!DOCTYPE html>


<html>
<head runat="server">
<title>Ext.NET Examples</title>


<link href="resources/desktop.css" rel="stylesheet" />


<script>
var tile = function () {
Ext.net.Desktop.desktop.tileWindows();
};


var cascade = function () {
Ext.net.Desktop.desktop.cascadeWindows();
};


var initSlidePanel = function () {
this.setHeight(Ext.net.Desktop.desktop.body.getHei ght());


if (!this.windowListen) {
this.windowListen = true;
this.show();


this.el.alignTo(Ext.net.Desktop.desktop.body, 'tl-tr', [0, 0]);
Ext.on("resize", initSlidePanel, this);
}
};
</script>
</head>
<body>
<ext:ResourceManager runat="server">
<Listeners>
<WindowResize Handler="Ext.net.Bus.publish('App.Desktop.ready');" Buffer="500" />
</Listeners>
</ext:ResourceManager>


<ext:Desktop ID="Desktop1" runat="server">
<Modules>
<ext:DesktopModule ModuleID="Hello" AutoRun="true">
<Window>
<ext:Window runat="server"
Plain="true"
Padding="10"
Width="150"
Height="100"
Title="Greeting"
CloseAction="Destroy"
Maximizable="false"
Minimizable="false">
<Content>
Welcome to Ext.Net desktop!
</Content>
</ext:Window>
</Window>
</ext:DesktopModule>


<ext:DesktopModule ModuleID="notepad">
<Shortcut Name="Notepad" IconCls="x-notepad-shortcut" SortIndex="2" />
<Launcher Text="Notepad" Icon="ApplicationForm" />
<Window>
<ext:Window runat="server"
Title="Notepad"
Width="750"
Height="400"
Icon="ApplicationForm"
AnimCollapse="false"
Border="false"
HideMode="Offsets"
Layout="FitLayout"
CloseAction="Destroy">
<Items>
<ext:HtmlEditor
runat="server"
Text="Some <b>rich</b> <font color='red'>text</font> goes <u>here</u><br>Give it a try!" />
</Items>
</ext:Window>
</Window>
</ext:DesktopModule>



<ext:DesktopModule ModuleID="add-module">
<Shortcut Name="Render dynamic module" Handler="function () {#{DirectMethods}.AddNewModule();}" X="200" Y="100" TextCls="x-long-label">
</Shortcut>
</ext:DesktopModule>



</Modules>


<DesktopConfig Wallpaper="resources/wallpapers/blue.jpg" ShortcutDragSelector="true">
<ShortcutDefaults IconCls="x-default-shortcut" />
<ContextMenu>
<ext:Menu runat="server">
<Items>
<ext:MenuItem runat="server" Text="Change Settings" />
<ext:MenuSeparator runat="server" />
<ext:MenuItem runat="server" Text="Tile" Handler="tile" Icon="ApplicationTileVertical" />
<ext:MenuItem runat="server" Text="Cascade" Handler="cascade" Icon="ApplicationCascade" />
</Items>
</ext:Menu>
</ContextMenu>


<Content>
<ext:Image runat="server" ImageUrl="resources/logo.png" StyleSpec="position:absolute;top: 50%;left: 50%;width: 77px; height: 78px;margin-top: -39px; margin-left: -39px;"/>
<ext:Image runat="server" ImageUrl="resources/powered.png" StyleSpec="position:absolute;right:10px;bottom:20px;width:300 px;height:39px;"/>
<ext:DisplayField runat="server" Text="You can place controls to desktop" FieldStyle="color:white;font-size:24px;" StyleSpec="position:absolute;left: 50%; bottom: 100px;margin-left: -180px;"/>
<ext:DisplayField runat="server" Text="Move mouse to the right edge -->" FieldStyle="color:white;font-size:24px;" StyleSpec="position:absolute;right:50px;top:50px;"/>


<ext:Toolbar runat="server" Width="545" Floating="true" ClassicButtonStyle="true" Flat="true" Border="false" Shadow="false">
<Defaults>
<ext:Parameter Name="IconAlign" Value="top" />
<ext:Parameter Name="Width" Value="105" />
<ext:Parameter Name="Icon" Value="resources/cmd.png" />
<ext:Parameter Name="Scale" Value="large" />
<ext:Parameter Name="Handler" Value="function () {Ext.Msg.alert('Launch', this.text);}" Mode="Raw" />
</Defaults>
<Items>
<ext:Button runat="server" Text="Word" />
<ext:Button runat="server" Text="Excel" />
<ext:Button runat="server" Text="Notepad" />
<ext:Button runat="server" Text="Paint" />
<ext:Button runat="server" Text="Explorer" />
</Items>
<MessageBusListeners>
<ext:MessageBusListener Name="App.Desktop.ready" Handler="this.el.anchorTo(Ext.net.Desktop.desktop.body, 'c-b', [0, -50]);" />
</MessageBusListeners>
</ext:Toolbar>
</Content>
</DesktopConfig>


<StartMenu Title="Ext.Net Desktop" Icon="Application" Height="300">
<ToolConfig>
<ext:Toolbar runat="server" Width="100">
<Items>
<ext:Button runat="server" Text="Settings" Icon="Cog" />
<ext:Button runat="server" Text="Logout" Icon="Key">
<DirectEvents>
<Click OnEvent="Logout_Click">
<EventMask ShowMask="true" Msg="Good Bye..." MinDelay="1000" />
</Click>
</DirectEvents>
</ext:Button>
</Items>
</ext:Toolbar>
</ToolConfig>
</StartMenu>


<TaskBar TrayWidth="120">
<QuickStart>
<ext:Toolbar runat="server" Width="80">
<Items>
<ext:Button runat="server" Handler="tile" Icon="ApplicationTileVertical" OverflowText="Tile windows">
<QTipCfg Text="Tile windows" />
</ext:Button>


<ext:Button runat="server" Handler="cascade" Icon="ApplicationCascade" OverflowText="Cascade windows">
<QTipCfg Text="Cascade windows" />
</ext:Button>
</Items>
</ext:Toolbar>
</QuickStart>


<Tray>
<ext:Toolbar runat="server">
<Items>
<ext:Button ID="LangButton" runat="server" Text="EN" Cls="x-bold-text" MenuAlign="br-tr" ArrowVisible="false">
<Menu>
<ext:Menu runat="server">
<Items>
<ext:CheckMenuItem runat="server" Group="lang" Text="English" Checked="true" CheckHandler="function (item, checked) {checked && #{LangButton}.setText('EN');}" />
<ext:CheckMenuItem runat="server" Group="lang" Text="French" CheckHandler="function (item, checked) {checked && #{LangButton}.setText('FR');}" />
<ext:MenuSeparator runat="server" />
<ext:MenuItem runat="server" Text="Show the Language Bar" />
</Items>
</ext:Menu>
</Menu>
</ext:Button>
<ext:ToolbarFill runat="server" />
</Items>
</ext:Toolbar>
</Tray>
</TaskBar>
<Listeners>
<Ready BroadcastOnBus="App.Desktop.ready" />
</Listeners>
</ext:Desktop>


<ext:Panel runat="server" Title="Slide panel" Frame="true" Width="250" Layout="AccordionLayout" Floating="true" Shadow="false" Hidden="true">
<Items>
<ext:Panel runat="server" Title="Section 1" Icon="User" />
<ext:Panel runat="server" Title="Section 2" Icon="UserB" />
<ext:Panel runat="server" Title="Section 3" Icon="UserB" />
<ext:Panel runat="server" Title="Section 4" Icon="UserB" />
<ext:Panel runat="server" Title="Section 5" Icon="UserB" />
</Items>
<MessageBusListeners>
<ext:MessageBusListener Name="App.Desktop.ready" Fn="initSlidePanel" />
</MessageBusListeners>
<Plugins>
<ext:MouseDistanceSensor runat="server" Opacity="false" Threshold="25">
<Listeners>
<Near Handler="this.component.el.alignTo(Ext.net.Desktop.desktop. body, 'tr-tr', [0, 0], true);" />
<Far Handler="this.component.el.alignTo(Ext.net.Desktop.desktop. body, 'tl-tr', [0, 0], true);" />
</Listeners>
</ext:MouseDistanceSensor>
</Plugins>
</ext:Panel>


<%--Modules from User controls--%>
<ext:Container runat="server" ID="modulescon" />
<mod:GridWindow runat="server" />
<mod:SystemStatus runat="server" />
</body>
</html>

fabricio.murta
Sep 28, 2016, 12:28 AM
Hello @fotis! You are right, sorry! I tricked myself into believing the solution from that forum thread worked. I did something at my side that was exactly what you provided, but forgot a change in the control that hid the error.

Let's switch to a clearer and shorter version to reproduce the issue, eh? What about, maybe:

61559-default.aspx


<%@ Page Language="C#" %>

<%@ Import Namespace="Ext.Net.Utilities" %>

<script runat="server">
[DirectMethod(ShowMask=true)]
public void AddNewModule()
{
var customControlHandler = this.LoadControl("61559-dynModule.ascx");

DesktopModuleProxy control2 = ControlUtils.FindControl<DesktopModuleProxy>(customControlHandler);
control2.RegisterModule();

modulescon.ContentControls.Add(control2);
modulescon.UpdateContent();
}

[DirectMethod(ShowMask = true)]
public void Broken_AddNewModule()
{
var customControlHandler = this.LoadControl("61559-dynModule.ascx");

DesktopModuleProxy control2 = ControlUtils.FindControl<DesktopModuleProxy>(customControlHandler);
control2.RegisterModule();
}

</script>

<!DOCTYPE html>
<html>
<head runat="server">
<title>Ext.NET Examples</title>
</head>
<body>
<ext:ResourceManager runat="server" />

<ext:Desktop ID="Desktop1" runat="server">
<Modules>
<ext:DesktopModule ModuleID="add-module">
<Shortcut Name="Broken module" Handler="function () {App.direct.Broken_AddNewModule();}" />
</ext:DesktopModule>
<ext:DesktopModule ModuleID="add-modjule">
<Shortcut Name="Working module" Handler="function () {App.direct.AddNewModule();}" />
</ext:DesktopModule>
</Modules>
</ext:Desktop>

<%--Modules from User controls--%>
<ext:Container runat="server" ID="modulescon" />

<%-- Uncomment below to statically add the control. --%>
<%--<%@ Register Src="61559-dynModule.ascx" TagPrefix="mod" TagName="DynModule" %>
<mod:DynModule runat="server" />--%>
</body>
</html>


61559-dynModule.ascx


<%@ Control Language="C#" %>

<script>
var sayHello = function () {
Ext.Msg.alert("Message", "Control-scoped script!");
}
</script>

<ext:DesktopModuleProxy runat="server">
<Module ModuleID="dynMod">
<Shortcut Name="Dynamic Module" QTip="Load a dynamically defined module" />
<Launcher Text="Dynamic Module" />
<Window>
<ext:Window
runat="server"
Width="250"
Height="400"
Title="Blank window">
<%-- Work around: This will define a function in global space for the button to work. --%>
<PreInit Handler="window.sayHelloGlobal = function() { Ext.Msg.alert('Message', 'Component-scoped, global script!'); };" />
<Items>
<ext:Button runat="server" Text="Run script from control" Handler="sayHello();" />
<ext:Button runat="server" Text="Run script with workaround" Handler="sayHelloGlobal();" />
<ext:Button runat="server" Text="Run script from component" Handler="Ext.Msg.alert('Message', 'Component-scoped script!');" />
</Items>
</ext:Window>
</Window>
</Module>
</ext:DesktopModuleProxy>


I will be working on this example to see whether exists a way to imbue back the script block to the component. Hope to be able to come back with a positive answer soon.

Maybe for now you want to consider using one of the "working" approaches in the dynamic control window's buttons.

fabricio.murta
Sep 29, 2016, 5:48 AM
Hello!

If the example I provided above is right, then finally the reason becomes clear.

How do we expect the script block to be added to the container content if what we are adding is just the Ext.NET desktop module? The entire custom control must be added!

In other words, instead of adding the control2 which is just the DesktopModuleProxy part of the whole control to the placeholder container, then add the whole customControlHandler!

I hope this helps!

fotis
Oct 01, 2016, 6:46 PM
Thank you Fabricio! This has worked indeed!

fotis
Oct 01, 2016, 8:28 PM
Hi Fabricio,

js code runs ok now but seems that Ext.net controls are not accessible from dynamically add script code. Check below extension of the example. Store1 is not accessible when module loads dynamically (works fine if is statically added)
61559-dynModule.ascx

<%@ Control Language="C#" %>

<script runat="server">

public void RefreshDataSet(object sender, StoreReadDataEventArgs e)
{
this.Store1.DataSource = new object[]
{
new object[] { "3m Co", 71.72, 0.02, 0.03, "9/1 12:00am" },
new object[] { "Alcoa Inc", 29.01, 0.42, 1.47, "9/1 12:00am" },
new object[] { "Altria Group Inc", 83.81, 0.28, 0.34, "9/1 12:00am" },
};
}
</script>


<ext:XScript ID="XScript1" runat="server">
<script>
var sayHello = function () {
#{Store1}.reload();
}
</script>
</ext:XScript>


<ext:DesktopModuleProxy runat="server">
<Module ModuleID="dynMod">
<Shortcut Name="Dynamic Module" QTip="Load a dynamically defined module" />
<Launcher Text="Dynamic Module" />
<Window>
<ext:Window
runat="server"
Width="250"
Height="400"
Title="Blank window">


<%-- Work around: This will define a function in global space for the button to work. --%>
<PreInit Handler="window.sayHelloGlobal = function() { Ext.Msg.alert('Message', 'Component-scoped, global script!'); };" />
<Items>
<ext:Button runat="server" Text="Run script from control" Handler="sayHello();" />
<ext:Button runat="server" Text="Run script with workaround" Handler="sayHelloGlobal();" />
<ext:Button runat="server" Text="Run script from component" Handler="Ext.Msg.alert('Message', 'Component-scoped script!');" />
<ext:GridPanel
ID="GridPanel1"
runat="server"
Title="Array Grid"
Width="700"
Height="350">
<Store>
<ext:Store ID="Store1" runat="server" OnReadData="RefreshDataSet">
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="company" />
<ext:ModelField Name="price" Type="Float" />
<ext:ModelField Name="change" Type="Float" />
<ext:ModelField Name="pctChange" Type="Float" />
<ext:ModelField Name="lastChange" Type="Date" DateFormat="M/d hh:mmtt" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<ColumnModel>
<Columns>
<ext:Column runat="server" Text="Company" DataIndex="company" Flex="1" />
<ext:Column runat="server" Text="Price" DataIndex="price"/>
<ext:Column runat="server" Text="Change" DataIndex="change"/>
<ext:Column runat="server" Text="Change" DataIndex="pctChange"/>
<ext:DateColumn runat="server" Text="Last Updated" DataIndex="lastChange" Width="120" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:RowSelectionModel runat="server" />
</SelectionModel>

</ext:GridPanel>
</Items>

</ext:Window>
</Window>
</Module>
</ext:DesktopModuleProxy>

Any idea what is wrong as it is a common application scenario?

fabricio.murta
Oct 03, 2016, 7:21 PM
Hello @fotis!

As for a small part of the problem, is that you were using the #{Store1}.reload syntax, that won't work in all situations.

Change it to App.Store1 and voila... we get into another error, now from server-side. As the resource is being added dynamically, more steps are probably necessary to register the component -- if possible at all in this approach you're taking.

As a workaround for now I could suggest using the window with an iframe loader to load its contents with full support. This way we can rely on a full page life cycle, fully handled by Ext.NET and all inner controls properly registered in a separate Ext.NET resources manager.

fotis
Oct 04, 2016, 8:30 AM
Thank you Fabricio, yes iframe should be the best solution as we are building a complex app, so not everything can go on native modules on desktop.