[CLOSED] show / hide label in form panel using data bind

  1. #1

    [CLOSED] show / hide label in form panel using data bind

    hello,

    I want to show / hide a label in form panel (ext.net mvc) using data binding.
    So based on the store data which is bind into the form, the label will be show / hide accordingly. Please guide me how to do this.

    Thanks in advance.
    Last edited by fabricio.murta; May 08, 2023 at 5:04 AM.
  2. #2
    Hello, @user2022!

    You will do something similar to the example and thread related to your previous post. Except, instead of looking up a checkbox's "checked" state, you'll be comparing data from the store. And instead of the disabled property, you'll be referring to the hidden one.

    It may be more challenging than it sounds; it deeply depends on how you model your page. I suggest you draft a simplified test case for yourself before going into the complete solution, such that if you get stuck in some aspect of the functionality, you could easily share the code here so we could pinpoint you what's left to make it work.

    Hope this helps!
    Fabrício Murta
    Developer & Support Expert
  3. #3
    Hello fabricio.murta,

    below is the simple test case:
        @(
            X.Store().ID("storeData").Fields(f =>
            {
                f.Add(new string[] { "Code", "Name" });
                f.Add("IsActive", ModelFieldType.Boolean);
            })
        )
        @(
            X.FormPanel().ID("frmEdit").Margin(5).Layout(LayoutType.Border).Padding(0).Frame(true).StyleSpec("background-color: #fff;").ViewModel(true)
                .FieldDefaults(fd =>
                {
                    fd.LabelAlign = LabelAlign.Left;
                    fd.MsgTarget = MessageTarget.Qtip;
                    fd.LabelWidth = 150;
                }).Items(
    
                X.FieldSet().Border(false).ColumnWidth(1).Items(
                    X.DisplayField().DataIndex("Code").FieldLabel("Code"),
                    X.TextField().Name("Name").DataIndex("Name").FieldLabel("Name"),
                    X.Checkbox().InputValue("true").UncheckedValue("false").Name("IsActive").DataIndex("IsActive").Reference("chkIsActive"),
    
                    X.Label().Text("The company has been de-activated!").Bind(c => c.Add(new Parameter("hidden", "{!chkIsActive.checked}")))
                )
    
            ).TopBarItem(
    
                X.Button().ID("cmdSave").Text("Save").OnClientClick("controller.event.onUpdateData()")
    
            )
        )
    
        <script>
            Ext.onReady(function () {
    
                App.storeData.insert(0, {
                    Code: '001',
                    Name: 'company 001',
                    IsActive: true
                });
                App.storeData.commitChanges();
                App.frmEdit.loadRecord(App.storeData.getAt(0));
    
            });
    
            const controller = {
                event: {
                    onUpdateData: function () {
                        App.frmEdit.updateRecord();
                        console.log('updating data: ', App.frmEdit.getRecord().getData());
                    }
                }
            }
        </script>
    I try to load the data to my form using the store in this case, the binding has been defined in the label with text: "The company has been de-activated!".

    I guess that the "ViewModel(true)" setting allow the databinding working within the form context but not with the store data, the label hide/show properly if I use: "{!chkIsActive.checked}", but it not work if I define the store property there "{!IsActive}".

    please help to show me how to work with the binding in this case using store and point me to some online documents where I can read in more detail about how the ViewModel and binding feature working in ext.net.

    Thanks a lot in advance
  4. #4
    Hello again, @user2022!

    Quote Originally Posted by user2022
    I guess that the "ViewModel(true)" setting allow the databinding working within the form context but not with the store data, the label hide/show properly if I use: "{!chkIsActive.checked}", but it not work if I define the store property there "{!IsActive}".
    And yes, it can't simply guess what's to track. If you do ViewModel(true) you enable tracking of references within that context, just how adding .Reference("chkIsActive") to the checkbox promptly makes it able to be queried.

    Without specifying anything to the store, it will be... well... a store! So you need to, somehow, add a reference to its "IsActive" state. Now another problem is raised: a store can contain various records, how should even I know how it should say "IsActive" is true? I suppose it's the loaded record in the form which, well, would just be record loaded in the form, then.

    Anyway, to simplify our first iteration, I'll just consider that the first record (if any) in the store, is to give the form its "is checked" state to show the label.

    So I'll add another label to the form: the existing one will reflect the checkbox state in the form itself, the other shall be displayed if and only if the first record in the store has its IsActive field as true.

    Then, in summary:

    - add the store to the viewmodel, so it becomes aware of the store as its tracked data (instead of true, the ViewModel() will receive an object setting it up)
    - add a Formula to fetch the 1st record IsActive state as the store changes
    - add the extra label, rewording the labels to be clearer which one is displayed in which situation

    With that, extra formatting, and stripping the need to a layout from your general test case, it became:

    @{
        Layout = null;
        var X = Html.X();
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Component State - Ext.Net Examples</title>
        <script type="text/javascript">
            Ext.onReady(function () {
    
                App.storeData.insert(0, {
                    Code: '001',
                    Name: 'company 001',
                    IsActive: true
                });
                App.storeData.commitChanges();
                App.frmEdit.loadRecord(App.storeData.getAt(0));
    
            });
    
            const controller = {
                event: {
                    onUpdateData: function () {
                        App.frmEdit.updateRecord();
                        console.log('updating data: ', App.frmEdit.getRecord().getData());
                    }
                }
            }
        </script>
    </head>
    <body>
        <div>
            @Html.X().ResourceManager()
    
            <h1>Component State</h1>
            <p>This example shows how to use basic data binding to bind the state of one component to the state of another.</p>
    
            @(
                 X.Store()
                    .ID("storeData")
                    .Model(X.Model()
                        .Fields(f =>
                        {
                            f.Add(new string[] { "Code", "Name" });
                            f.Add("IsActive", ModelFieldType.Boolean);
                        })
                    )
            )
    
            @{ 
                var storeBindingModel = new
                {
                    stores = new
                    {
                        storeData = JRawValue.From("App.storeData")
                    },
                    formulas = new
                    {
                        firstRecordActive = new
                        {
                            bind = new
                            {
                                bindTo = "{storeData}",
                                deep = true
                            },
                            get = JRawValue.From("function (store) { return store.count() > 0 ? store.getAt(0).data.IsActive : false; }")
                        }
                    }
                };
            }
            @(
                X.FormPanel()
                    .ID("frmEdit")
                    .Height(800)
                    .Margin(5)
                    .Layout(LayoutType.Border)
                    .Padding(0)
                    .Frame(true)
                    .StyleSpec("background-color: #fff;")
                    .ViewModel(storeBindingModel)
                    .FieldDefaults(fd =>
                    {
                        fd.LabelAlign = LabelAlign.Left;
                        fd.MsgTarget = MessageTarget.Qtip;
                        fd.LabelWidth = 150;
                    })
                    .Items(
                        X.FieldSet().ColumnWidth(1).Items(
                            X.DisplayField().DataIndex("Code").FieldLabel("Code"),
                            X.TextField().Name("Name").DataIndex("Name").FieldLabel("Name"),
                            X.Checkbox().InputValue("true").UncheckedValue("false").Name("IsActive").DataIndex("IsActive").Reference("chkIsActive"),
                            X.Label().Html("The loaded record in the form has <pre style=display:inline;>IsActive</pre> as <pre style=display:inline;>true</pre>!").Bind(c => c.Add(new Parameter("hidden", "{!chkIsActive.checked}"))),
                            X.Label().Html("<br />The store's first record has <pre style=display:inline;>IsActive</pre> as <pre style=display:inline;>true</pre>!").Bind(c => c.Add(new Parameter("hidden", "{!firstRecordActive}")))                    )
                    )
                    .TopBarItem(
                        X.Button().ID("cmdSave").Text("Save").OnClientClick("controller.event.onUpdateData()"
                    )
                )
        )
        </div>
    </body>
    </html>
    So:

    - In lines 54 thru 74 I set up the ViewModel config object, in which
    - lines 57-60 binds it to the external store (it is necessarily wrapped in a stores property)
    - Lines 61-72 defines a "formula" to do whatever math is necessary to retrieve the status we want to consider while checking for the second label's hidden state
    - Line 97 adds the additional label, checking the formula result in real-time

    So when you play the example, the labels follows the states as they are updated (as long as the only record in the store is the displayed one).

    You can use two-way binding to the App.frmEdit's Code field to pass it as a filter to the formula / store query, as to retrieve the exact loaded record while checking how to fill its true/false result.

    A remark about all this would be, in case the grid has several records, any change to the grid will trigger re-evaluation of the formula, and this can become cumbersome. If performance becomes a concern, syncing the state via usual events (Listeners, DirectEvents) would be the way to go. Store binding usually is more meaningful when any data change is likely to cause changes to the bound page.

    You can also link specific records (and update them) directly in the ViewModel (see documentation on Ext.app.ViewModel here). But again, you're already binding the record to the form itself, so perhaps best (performance-wise) in case that label is to be shown when data is saved, would be to simply change its state when the form is loaded (contents changed) -and- when the save button is clicked.

    The "performatic" event-based solution in the paragraph above would miss, though, if something else in the same page could change the store data (a button to reload the store, maybe, pulling changed data from the server). But then, that very change probably should trigger an event to sync the data loaded in form and ensure its data (like, the name, or if the code still exists) are up-to-date; and this same event would also update the IsActive label in the form.

    Notwithstanding, if the store data is displayed in a grid, you could also bind the form contents to the selection of the grid, thus checking the form could automatically propagate the change to the store through the grid. See a complete example of this functionality here; it also binds the data with charts in the page.

    One way or another, I hope this helps you develop your view with the best options.
    Fabrício Murta
    Developer & Support Expert
  5. #5
    Hello fabricio.murta,

    many thanks for your help, please close this thread.
  6. #6
    Glad it helped, thanks for the feedback! Closing thread...
    Fabrício Murta
    Developer & Support Expert

Similar Threads

  1. [CLOSED] Hide field label separator of form panel
    By speedstepmem4 in forum 3.x Legacy Premium Help
    Replies: 6
    Last Post: Jan 19, 2015, 11:11 AM
  2. [CLOSED] Show hide a ImageCommandColumn AFTER the Grid Data are loaded
    By Peter.Treier in forum 2.x Legacy Premium Help
    Replies: 3
    Last Post: Aug 26, 2014, 5:47 PM
  3. Replies: 4
    Last Post: Apr 08, 2014, 5:45 PM
  4. Replies: 1
    Last Post: Oct 04, 2013, 5:22 AM
  5. [CLOSED] Hide and show a container if no data
    By PriceRightHTML5team in forum 2.x Legacy Premium Help
    Replies: 4
    Last Post: Aug 13, 2013, 12:10 PM

Posting Permissions