MVC: TreePanel + FormPanelFor - How to load Record depending on Item clicked in TreePanel

  1. #1

    MVC: TreePanel + FormPanelFor - How to load Record depending on Item clicked in TreePanel

    Hi,

    I have some difficulties to understand some basic concepts how I can load C# model instances asynchronous into Panels.
    Lets assume I have a TreePanel, like in some examples which gets a collection of Nodes through a ActionMethod + a FormPanelFor for the page model:

    @model Ext.Models.Company
    @(Html.X().TreePanel()
                .Store(Html.X().TreeStore()
                    .Proxy(Html.X().AjaxProxy().Url(Url.Action("GetChildren")))
                )
                .Root(Html.X().Node().NodeID("0").Text("Root"))
                .Listeners(l => {
                    l.ItemClick.Handler = "alert(record.data.id);";
                })
        )
    @(Html.X().FormPanelFor(m => m))
    The ASP MVC Controller has the following methods:

    public StoreResult GetChildren(string node);
    public StoreResult GetCompanyById(string id);
    How can I say now in the l.ItemClick.Handler that I want to call the GetCompanyById method and load it into the FormPanelFor.

    If someone can recommend me some good book or other material about Ext.NET MVC I would be also very happy. The examples on the page are nice but I do not really understand the concepts of the communication between the clientside JavaScript and the C# backend. I also tried to Ext.NET Web Application Development but I feel like it's not so helpful with MVC since it's mostly about WebForms.

    I would be very thankful for some help.
  2. #2

    Loading Form based on TreePanel selected node

    Hi Peter,

    I recently went through this and my approach is as follows:

    1) Broadcast on the Bus the ItemClick event. This would allow you to pickup the event from other components in the future, not just the form you want to load. My paradigm is: the TreePanel broadcasts a signal of the ItemClick event and doesn't need to know who's listening. I'm doing a lot of it on code-behind and in my case it looks like:

    this.Listeners.ItemClick.BroadcastOnBus = this.ClientID + ".onNodeClick";
    where "this" is the class that I'm using to create the TreePanel

    2) On the FormPanel that you'd like to load, define a MessageBusDirectEvent. This will listen to the ItemClick event and load itself based on the information attached to the broadcast. In my case, I'm defining this in my code as:

    this.MessageBusDirectEvents.Add(new MessageBusDirectEvent()
                {
                    Name = "App.TreePanelId.onNodeClick",
                    EventMask = {CustomTarget = this.ClientID, ShowMask = true },
                    ExtraParams = {new Parameter() {Name = "nodeId", Value = "data.record.internalId", Mode = ParameterMode.Raw}},
                    Action = "/GetNodeDetails",
                    Success = "loadDetails(result,el)"
                });
    where "this" is the class I'm using to define the FormPanel (or any other type of component that you'd like to react to the same event for that matter).

    3) As you can see in the code of Step 2, the DirectEvent also defines a JavaScript function which upon receipt of the details related to that node would actually load values on each of the form fields. The general form of this would be:

    <fieldClientId>.setValue(result.<your-field-value-returned-from-the-controller>
    I don't know whether this is the most correct approach, but it works for me.

    Good luck.
  3. #3
    Hey AussieChuck,

    thanks for your input, but I still have some issues understanding this concepts in ASP MVC:

    So this is my current view now (Gst -> Index.cshtml Razor view, simplified):
    
    @(X.Panel()
            .Items(
                 X.TreePanel()
                    .ID("GstTreePanel")
                    .Store(
                        Html.X().TreeStore()
                            .Proxy(Html.X().AjaxProxy().Url(Url.Action("GetTreeItems")))
                        )
                    .Listeners(l =>
                    {
                        l.ItemClick.BroadcastOnBus = "GstTreePanel.onNodeClick";
                    }),
                    X.FormPanelForModel()
                    .ID("GStDetailsForm")
                    .MessageBusDirectEvents(new MessageBusDirectEvent()
                    {
                        Name = "App.GstTreePanel.onNodeClick",
                        EventMask = { CustomTarget = "GstTreePanel", ShowMask = true },
                        ExtraParams = { new Parameter() { Name = "id", Value = "data.record.internalId", Mode = ParameterMode.Raw } },
                        Action = "/GetGstById",
                        Success = "loadGStDetails(result,el)"
                    })
            )
    )
    And this is my controller GStController:

       
    
    public class GstController : ExtDirectController<GSt>
    {
            public ActionResult GetGstById(string id) {...}
            public StoreResult GetTreeItems(string node) {...}
    }
    So my first issue is: this.ClientID doesn't exist so I used the ID of the TreePanel. Hope this is right?
    I don't really understand the concept of the MessageBusDirectEvent and don't find some clear documentation about this either. For the custom target I used the same ID (the TreePanel) and for the Action the Action Method Name of the controller.

    But the controller function never gets called so I am not sure what I am doing wrong.
  4. #4

    MessageBusDirectEvents

    Hi peter594,

    I'm with you, sometimes it might be confusing to understand what's going on.

    The listener declared in your treepanel doesn't have to be named in a specific way, it's just a name, although it's good practice to uniquely name it in a logical manner, like <namespace>.<componentId>.<eventname> like "App.GstTreePanel.onNodeClick".

    Now in your case you're telling the treepanel to shout "GstTreePanel.onNodeClick" to the Bus. However, your're asking the form to listen to "App.GstTreePanel.onNodeClick", that's why the controller event is not triggered. The form is not listening to the right "words". To fix this, just make sure both the listener declaration and the name of the event you're listening to on other components are the same.

    All components have a ClientID, either generated automatically or if you specify a component ID, it would be built appending the component ID to the namespace, for example, your ID="GstTreePanel" would have a ClientID = "App.GstTreePanel".

    In regards to the MessageBusDirectEvents. This is a function of Ext.Net that dynamically constructs a JavaScript function based on your specifications which has the purpose of submitting an asynchronous request to the server controller/method you specify.

    If you'd like you could visualize it this way:

    1) The client (browser) calls your Index view for the first time.
    2) The server responds with some HTML and a number of JS files to build the view accordingly.
    <These next steps happen all in the client>
    3) When you click on a TreePanel with a Listener defined, it will "emit" an event to the Bus.
    4) The Bus notifies all the Observers.
    5) If an observer "hears" a matching event name, it triggers its own method.
    6) The dynamically created JS function defined by the MessageBusDirectEvent method, packages a request with the ExtraParams you defined and sends this request to the server asynchronously (i.e. the whole page is not refreshed).
    <Back in the server>
    7) The server controller method receives your request, performs whatever tasks you've programmed in the controller method and returns a response.
    <Again on the client>
    8) The client receives the response and if you defined a Success or Failure functions (basically JS callbacks) the client performs whatever tasks you've programmed in those functions using the server's response (which can be JSON data, views, whole new components, etc.)

    I hope this helps you.

    Cheers.
  5. #5
    Hey AussieChuck,

    thanks a lot for your detailed description of the concepts, I got it to work :)

Similar Threads

  1. Replies: 3
    Last Post: Jun 04, 2013, 11:33 PM
  2. [CLOSED] Menu item - clicked row record
    By bayoglu in forum 2.x Legacy Premium Help
    Replies: 1
    Last Post: Feb 17, 2013, 2:39 AM
  3. [CLOSED] Treepanel - Determine what column was clicked
    By fordprefect in forum 2.x Legacy Premium Help
    Replies: 2
    Last Post: Dec 12, 2012, 4:10 PM
  4. [CLOSED] TreePanel with ContextMenu retrieve NodeID of node clicked
    By taylorjp2000 in forum 2.x Legacy Premium Help
    Replies: 3
    Last Post: Nov 13, 2012, 3:17 PM
  5. Replies: 3
    Last Post: May 25, 2010, 4:29 PM

Posting Permissions