Enable/Disable Gridpanel fields on button click.

  1. #1

    Enable/Disable Gridpanel fields on button click.

    Hello,
    I have a gridpanel with two buttons in the topbar/toolbar ("Edit Data" and "Save Data", "Cancel")

    Please see attached screenshot(it does not have the "Cancel" button yet).

    I have looked through examples and searched through the help topics but could not come up with a solution, here is what i need:


    1. When user gets to the page first time - the gridpanel loads with all the fields read-only. "Edit Data" button showing, "Save Data" and "Cancel" buttons hidden.

    2. When the user clicks "Edit Data", certain fields ("New Number", "New Name", "Note" on all the records become editable. Editable fields should be visually different from non-editable ones. "Edit Data" button disappears, "Save Data" and "Cancel" buttons appear.

    3. If user clicks "Save Data" button, data is updated in database, "Save Data" and "Cancel" buttons disappear, "Edit Data" button appears and all fields on all records become read-only.

    4. IF user clicks "Cancel" button, original data is reloaded in the grid, "Save Data" and "Cancel" buttons disappear, "Edit Data" button appears, and all fields on all records become read-only.


    Here is what I can't get to work:
    1. loop through all the records in the grid (or preferrably all the dirty records) to save data in the db. I could only find how to loop through the selected ones by using selection model. but in my case users may edit data in several rows and not necessarily have them selected.

    2. I could not make the buttons disappear, I was only able to disable them. Setting .Visible="false" seems to not do anything.

    3. Not sure how to apply different style to editable/read-only fields

    4. Not sure how to dynamically (when button is clicked) make fields editable/readonly (it was really easy with a regular asp.net gridview, but i need some help here).

    Thanks in advanceClick image for larger version. 

Name:	Screen Shot 2020-07-23 at 3.35.29 PM.png 
Views:	232 
Size:	60.6 KB 
ID:	25394,
    Dennis.
  2. #2
    Hi Dennis,

    Can you provided a simplified sample demonstrating as much of this scenario as you can. We can try to fill in the pieces that are not working.

    Some tips on creating samples for the forums:
    https://forums.ext.net/showthread.ph...ing-New-Topics
    Geoffrey McGill
    Founder
  3. #3
    Geoffrey, here is the sample. Thanks for your help!

    Test.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="EXTTestCases.Test" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <script type="text/javascript">
            var template = 'color:{0};';
    
            var change = function (value, meta) {
                meta.style = Ext.String.format(template, (value > 0) ? "green" : "red");
                return value;
            };
    
            var pctChange = function (value, meta) {
                meta.style = Ext.String.format(template, (value > 0) ? "green" : "red");
                return value + "%";
            };
    
            var statusRenderer = function (value) {
                var r = App.StoreCombo.getById(value);
    
                if (Ext.isEmpty(r)) {
                    return "";
                }
                return r.data.Name;
            };
        </script>
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
    
            <ext:ResourceManager runat="server" />
    
            <ext:Store ID="StoreCombo" runat="server">
                <Model>
                    <ext:Model runat="server" IDProperty="ID">
                        <Fields>
                            <ext:ModelField Name="ID" />
                            <ext:ModelField Name="Name" />
                        </Fields>
                    </ext:Model>
                </Model>
            </ext:Store>
    
            <ext:GridPanel ID="GridPanel1" runat="server" Title="Editable GridPanel" Width="1000">
                <Store>
                    <ext:Store ID="Store1" runat="server">
                        <Model>
                            <ext:Model runat="server" IDProperty="ID">
                                <Fields>
                                    <ext:ModelField Name="ID" Type="Int" />
                                    <ext:ModelField Name="Name" />
                                    <ext:ModelField Name="Number" />
                                    <ext:ModelField Name="NumberNew" />
                                    <ext:ModelField Name="NameNew" />
                                    <ext:ModelField Name="Note" />
                                    <ext:ModelField Name="TransferStatus_ID" Type="Int" />
                                </Fields>
                            </ext:Model>
                        </Model>
                    </ext:Store>
                </Store>
                <ColumnModel runat="server">
                    <Columns>
                        <ext:Column runat="server" Text="Name" DataIndex="Name" Flex="1">
                        </ext:Column>
                        <ext:Column runat="server" Text="Number" DataIndex="Number" Flex="1">
                        </ext:Column>
                        <ext:Column runat="server" Text="Name New" DataIndex="NameNew" Flex="1">
                            <Editor>
                                <ext:TextField runat="server" />
                            </Editor>
                        </ext:Column>
                        <ext:Column runat="server" Text="Number New" DataIndex="NumberNew" Flex="1">
                            <Editor>
                                <ext:TextField runat="server" />
                            </Editor>
                        </ext:Column>
                        <ext:Column runat="server" Text="Note" DataIndex="Note" Flex="1">
                            <Editor>
                                <ext:TextField runat="server" />
                            </Editor>
                        </ext:Column>
                        <ext:Column runat="server" DataIndex="TransferStatus_ID" Text="Status" Width="200">
                            <Renderer Fn="statusRenderer"></Renderer>
                            <Editor>
                                <ext:ComboBox ID="cbStatuses" StoreID="StoreCombo" DisplayField="Name" ValueField="ID" runat="server" />
                            </Editor>
                        </ext:Column>
                    </Columns>
                </ColumnModel>
                <TopBar>
                    <ext:Toolbar runat="server">
                        <Items>
                            <ext:Button
                                ID="btnEditGrid"
                                runat="server"
                                Text="Edit Grid"
                                OnDirectClick="EditGridButton_Click" Disabled="false" />
    
                            <ext:Button
                                ID="btnSaveChanges"
                                runat="server"
                                Text="Save Changes"
                                AutoLoadingState="true"
                                OnDirectClick="SaveChangesButton_Click" Disabled="true" />
                        </Items>
                    </ext:Toolbar>
                </TopBar>
                <SelectionModel>
                    <ext:CheckboxSelectionModel runat="server" Mode="Multi" />
                </SelectionModel>
                <View>
                    <ext:GridView runat="server"></ext:GridView>
                </View>
                <Plugins>
                    <ext:CellEditing runat="server" ClicksToEdit="1" />
                </Plugins>
            </ext:GridPanel>
        </form>
    </body>
    </html>
    Test.aspx.cs
    using System;
    using System.Collections.Generic;
    using Ext.Net;
    
    namespace EXTTestCases
    {
        public partial class Test : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                if (!X.IsAjaxRequest)
                {
                    this.BindData();
                }
            }
    
            private void BindData()
            {
                this.StoreCombo.DataSource = TransferStatus.GetAll();
                this.StoreCombo.DataBind();
    
                this.Store1.DataSource = Client.GetAll();
                this.Store1.DataBind();
            }
            
            public class TransferStatus
            {
                public int ID { get; set; }
                public string Name { get; set; }
    
                public static List<TransferStatus> GetAll()
                {
                    return new List<TransferStatus>
                           {
                               new TransferStatus {ID = 1, Name = "Pending"},
                               new TransferStatus {ID = 4, Name = "Accepted"},
                               new TransferStatus {ID = 7, Name = "Rejected"}
                           };
                }
            }
    
            protected void SaveChangesButton_Click(object sender, DirectEventArgs e)
            {
                X.Js.Call("Ext.suspendLayouts");
                this.btnEditGrid.Disabled = false;
                this.btnSaveChanges.Disabled = true;
                this.btnEditGrid.Focus();
                X.Js.Call("Ext.resumeLayouts", true);
            }
    
            protected void EditGridButton_Click(object sender, DirectEventArgs e)
            {
                X.Js.Call("Ext.suspendLayouts");
                this.btnEditGrid.Disabled = true;
                this.btnSaveChanges.Disabled = false;
                this.btnSaveChanges.Focus();
                X.Js.Call("Ext.resumeLayouts", true);
            }
    
        }
    
        public partial class Client
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public string Number { get; set; }
            public string Name_Overlay { get; set; }
            public string Number_Overlay { get; set; }
            public int TransferStatus_ID { get; set; }
            public string Note { get; set; }
    
            public static  List<Client> GetAll()
            {
                List<Client> clntList = new List<Client>();
    
                clntList.Add(new Client() { ID = 10, Name = "Client1", Number = "01", Note = "Client 1 Note", Number_Overlay = "01", Name_Overlay = "Client1", TransferStatus_ID = 1 });
                clntList.Add(new Client() { ID = 11, Name = "Client2", Number = "02", Note = "Client 2 Note", Number_Overlay = "02", Name_Overlay = "Client2", TransferStatus_ID = 7 });
    
                return clntList;
            }
    
        }
    }
  4. #4
    Hello @Dennis, and thanks for the test case!

    First I will point each issue you had with a possible way to address it, then I will post a suggestion of how your example could look like with these implemented.

    Quote Originally Posted by Dennis
    1. loop through all the records in the grid (or preferrably all the dirty records) to save data in the db. I could only find how to loop through the selected ones by using selection model. but in my case users may edit data in several rows and not necessarily have them selected.
    You want the grid store's dirty records. There are several examples which shows some ways you can sync stores to the server. Here are some:

    - GridPanel > Saving_Variations > HttpHandler
    - GridPanel > Saving_Variations > StoreCustomLogic
    - GridPanel > Saving_Variations > StoreEvents
    - GridPanel > Saving_Variations > WebService
    - GridPanel > Update > SqlDataSource
    - GridPanel > Update > AutoSave

    One particular approach to saving the grid data would be highlighted in this example:

    - GridPanel > Update > Batch

    That is, just submitting the changed data. If you are not interested in new rows (if your grid won't allow adding new records), you may want just getUpdatedRecords() instead of getChangedData() in the direct event parameter.

    Quote Originally Posted by Dennis
    2. I could not make the buttons disappear, I was only able to disable them. Setting .Visible="false" seems to not do anything.
    What you're missing here is that you are just setting properties/configs to already rendered components. They are already rendered, they won't re-read those until you re-render the component at all. What you want here is to call their respective setter methods. So change this.btnSaveChanges.Hidden = true; to this.btnSaveChanges.Hide(); and you should get what you want.

    You may notice just setting the config in some situations just works, and that would be true. But that's not always true and it may be confuse to guess which components get or not the "auto-call-setter" feature. So best rule of thumb would be to try to call the setter itself when there's one available. .Hide(), .Show(), .Disable(), .Enable(), or when there's client-side setter but not server-side, say, for a Html setting, you could this.MyComponent.Call("setHtml", "my inner content");. true/false and integer numbers are valid second arguments you can pass to the .Call() method.

    Quote Originally Posted by Dennis
    3. Not sure how to apply different style to editable/read-only fields
    One way through this is to give the editable cells (or the read-only ones) a CSS class. Just to "mark" them. Then you can draw a javascript function to loop throughout them and apply another CSS class with the effect you want (or just set the desired CSS styling). Likewise, another single "dim" method could step thru the elements with that "marker class" and de-apply the effect class or styles.

    Adapted sample

    The sample below should comply to your requirements, with some remarks:

    - When you click 'save' we are just getting and showing back the submitted value, you should parse them back accordingly (the batch save example should help with other details like clearing the 'dirty' state if desired and mapping it to an actual C# structure).
    - The "save" button is initially disabled. The grid store will enable and disable it as changes are triggered -- so that it is always disabled if there's nothing to submit.
    - The visual effects on editable cells are toggled by the save button's show/hide event.
    - The "editability" of cells in turn, are defined by the save button's hidden state. Technically the editable cells will always trigger edit when clicked, but they will just be denied until the "save" button is displayed -- "signalling" the page it is in "edit mode".
    - The "cancel" handler just calls again the data binding method, so the store is replaced (actually refreshed with whatever data is in the server at the moment it is called) with a whole new set of data. You can alternatively cycle thru the store data records and discard() the changes to every dirty record, but then new or removed records would need additional specific logic (but no server round-trip would be required when cancelling changes).
    - I have merged the two code blocks into a single block, with embedded code-behind, should be easier to copy-paste, and namespace-agnostic.

    <%@ Page Language="C#" %>
    
    <!DOCTYPE html>
    
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
                this.BindData();
            }
        }
    
        private void BindData()
        {
            this.StoreCombo.DataSource = TransferStatus.GetAll();
            this.StoreCombo.DataBind();
    
            this.Store1.DataSource = Client.GetAll();
            this.Store1.DataBind();
        }
    
        public class TransferStatus
        {
            public int ID { get; set; }
            public string Name { get; set; }
    
            public static List<TransferStatus> GetAll()
            {
                return new List<TransferStatus>
                {
                    new TransferStatus {ID = 1, Name = "Pending"},
                    new TransferStatus {ID = 4, Name = "Accepted"},
                    new TransferStatus {ID = 7, Name = "Rejected"}
                };
            }
        }
    
        protected void SaveChangesButton_Click(object sender, DirectEventArgs e)
        {
            var changes = e.ExtraParams["data_changes"];
    
            if (changes != null)
            {
                X.Toast("Got these records to update in database: " + changes);
            }
            else
            {
                X.Toast("No records to update.");
            }
    
            this.btnEditGrid.Enable();
            this.btnSaveChanges.Hide();
        }
    
        protected void EditGridButton_Click(object sender, DirectEventArgs e)
        {
            this.btnEditGrid.Hide();
            this.btnSaveChanges.Show();
            this.btnCancelEdit.Show();
        }
    
        protected void CancelEditButton_Click(object sender, DirectEventArgs e)
        {
            BindData();
            this.btnEditGrid.Show();
            this.btnSaveChanges.Hide();
            this.btnCancelEdit.Hide();
        }
    
        public class Client
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public string Number { get; set; }
            public string Name_Overlay { get; set; }
            public string Number_Overlay { get; set; }
            public int TransferStatus_ID { get; set; }
            public string Note { get; set; }
    
            public static List<Client> GetAll()
            {
                List<Client> clntList = new List<Client>();
    
                clntList.Add(new Client() { ID = 10, Name = "Client1", Number = "01", Note = "Client 1 Note", Number_Overlay = "01", Name_Overlay = "Client1", TransferStatus_ID = 1 });
                clntList.Add(new Client() { ID = 11, Name = "Client2", Number = "02", Note = "Client 2 Note", Number_Overlay = "02", Name_Overlay = "Client2", TransferStatus_ID = 7 });
    
                return clntList;
            }
        }
    </script>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <script type="text/javascript">
            var template = 'color:{0};';
    
            var change = function (value, meta) {
                meta.style = Ext.String.format(template, (value > 0) ? "green" : "red");
                return value;
            };
    
            var pctChange = function (value, meta) {
                meta.style = Ext.String.format(template, (value > 0) ? "green" : "red");
                return value + "%";
            };
    
            var statusRenderer = function (value) {
                var r = App.StoreCombo.getById(value);
    
                if (Ext.isEmpty(r)) {
                    return "";
                }
                return r.data.Name;
            };
    
            var highlightEditable = function () {
                document.querySelectorAll(".editable-cell").forEach(function (el) {
                    el.classList.add("editable-cell-highlight");
                });
            }
    
            var dimEditable = function () {
                document.querySelectorAll(".editable-cell").forEach(function (el) {
                    el.classList.remove("editable-cell-highlight");
                });
            }
        </script>
        <style type="text/css">
            .editable-cell { }
            .editable-cell-highlight {
                background-color: #f9ffd77f;
            }
        </style>
        <title>62941 - Disable Grid Cell Editing & more</title>
    </head>
    <body>
        <form id="form1" runat="server">
    
            <ext:ResourceManager runat="server" />
    
            <ext:Store ID="StoreCombo" runat="server">
                <Model>
                    <ext:Model runat="server" IDProperty="ID">
                        <Fields>
                            <ext:ModelField Name="ID" />
                            <ext:ModelField Name="Name" />
                        </Fields>
                    </ext:Model>
                </Model>
            </ext:Store>
    
            <ext:GridPanel
                ID="GridPanel1"
                runat="server"
                Title="Editable GridPanel"
                Width="1000">
                <CustomConfig>
                    <ext:ConfigItem Name="editingDisabled" Value="true" Mode="Raw" />
                </CustomConfig>
                <Store>
                    <ext:Store ID="Store1" runat="server">
                        <Model>
                            <ext:Model runat="server" IDProperty="ID">
                                <Fields>
                                    <ext:ModelField Name="ID" Type="Int" />
                                    <ext:ModelField Name="Name" />
                                    <ext:ModelField Name="Number" />
                                    <ext:ModelField Name="NumberNew" />
                                    <ext:ModelField Name="NameNew" />
                                    <ext:ModelField Name="Note" />
                                    <ext:ModelField Name="TransferStatus_ID" Type="Int" />
                                </Fields>
                            </ext:Model>
                        </Model>
                        <Listeners>
                            <DataChanged Handler="if (App.btnSaveChanges) App.btnSaveChanges.setDisabled(!this.isDirty())" />
                        </Listeners>
                    </ext:Store>
                </Store>
                <ColumnModel runat="server">
                    <Columns>
                        <ext:Column runat="server" Text="Name" DataIndex="Name" Flex="1">
                        </ext:Column>
                        <ext:Column runat="server" Text="Number" DataIndex="Number" Flex="1">
                        </ext:Column>
                        <ext:Column runat="server" Text="Name New" DataIndex="NameNew" Flex="1">
                            <Editor>
                                <ext:TextField runat="server" />
                            </Editor>
                        </ext:Column>
                        <ext:Column
                            runat="server"
                            Text="Number New"
                            DataIndex="NumberNew"
                            Flex="1"
                            TdCls="editable-cell">
                            <Editor>
                                <ext:TextField runat="server" />
                            </Editor>
                        </ext:Column>
                        <ext:Column
                            runat="server"
                            Text="Note"
                            DataIndex="Note"
                            Flex="1"
                            TdCls="editable-cell">
                            <Editor>
                                <ext:TextField runat="server" />
                            </Editor>
                        </ext:Column>
                        <ext:Column
                            runat="server"
                            DataIndex="TransferStatus_ID"
                            Text="Status"
                            Width="200"
                            TdCls="editable-cell">
                            <Renderer Fn="statusRenderer"></Renderer>
                            <Editor>
                                <ext:ComboBox ID="cbStatuses" StoreID="StoreCombo" DisplayField="Name" ValueField="ID" runat="server" />
                            </Editor>
                        </ext:Column>
                    </Columns>
                </ColumnModel>
                <TopBar>
                    <ext:Toolbar runat="server">
                        <Items>
                            <ext:Button
                                ID="btnEditGrid"
                                runat="server"
                                Text="Edit Grid"
                                OnDirectClick="EditGridButton_Click" />
                            <ext:Button
                                ID="btnSaveChanges"
                                runat="server"
                                Text="Save Changes"
                                AutoLoadingState="true"
                                Disabled="true"
                                Hidden="true">
                                <DirectEvents>
                                    <Click OnEvent="SaveChangesButton_Click">
                                        <ExtraParams>
                                            <ext:Parameter name="data_changes" Value="function() { return App.Store1.getChangedData(); }" Mode="Raw" />
                                        </ExtraParams>
                                    </Click>
                                </DirectEvents>
                                <Listeners>
                                    <Hide Fn="dimEditable" />
                                    <Show Fn="highlightEditable" />
                                </Listeners>
                            </ext:Button>
                            <ext:Button
                                ID="btnCancelEdit"
                                runat="server"
                                Text="Cancel"
                                AutoLoadingState="true"
                                OnDirectClick="CancelEditButton_Click"
                                Hidden="true" />
                        </Items>
                    </ext:Toolbar>
                </TopBar>
                <Listeners>
                    <BeforeEdit Handler="if (App.btnSaveChanges.hidden === true) return false" />
                </Listeners>
                <SelectionModel>
                    <ext:CheckboxSelectionModel runat="server" Mode="Multi" />
                </SelectionModel>
                <View>
                    <ext:GridView runat="server"></ext:GridView>
                </View>
                <Plugins>
                    <ext:CellEditing runat="server" ClicksToEdit="1" />
                </Plugins>
            </ext:GridPanel>
        </form>
    </body>
    </html>
    Hope this helps!
    Fabrício Murta
    Developer & Support Expert
  5. #5
    Fabricio, using your example I got this functionality working. Thanks !

Similar Threads

  1. [CLOSED] Enable and Disable GridCommand from Click in Button
    By osef in forum 2.x Legacy Premium Help
    Replies: 2
    Last Post: Feb 24, 2015, 6:02 PM
  2. Disable/enable all fields in a FormPanel
    By miles in forum 2.x Help
    Replies: 3
    Last Post: Oct 29, 2014, 4:25 PM
  3. Replies: 1
    Last Post: Jul 28, 2011, 4:25 PM
  4. [CLOSED] editable gridpanel enable/disable fields
    By schellappa in forum 1.x Legacy Premium Help
    Replies: 1
    Last Post: Jan 10, 2011, 7:17 PM
  5. Enable or disable the button
    By VietView in forum 1.x Help
    Replies: 4
    Last Post: Jan 09, 2009, 11:59 AM

Tags for this Thread

Posting Permissions