How to do data binding on dynamic form In Blazor ?

Posted 3 years ago by chandraev
Edited 3 years ago
0

Hi All,

I have requirement to create the tabular template entry form, I am generating the form dynamically using look.  But whenever i m giving input for one text box, then it is displaying in all the form. how can we full fill this requirement in Blazor

 

@page "/AddInspection"
@inject ICategoryService CategoryService
@inject IComponentService ComponentService
@inject ICategoryService CategoryService
@inject NavigationManager objNavigationManager
<h4>Inspection Form</h4>

<EditForm Model="@objIns" OnValidSubmit="CreateInspection">
    <div class="container">
        @foreach (var item in objServiceCateList)
        {
            if (item.IsVisible)
            {
                flag = "block";
            }
            else
            {
                flag = "none";
            }
            <div style="display:@flag">

                <table class="table table-bordered">

                    <thead>

                        <tr>
                            <th>@item.ServiceCategoryName</th>
                            <th>@item.ServiceCategoryCol2</th>
                            <th>@item.ServiceCategoryCol3</th>
                            <th>OK</th>
                            <th>S</th>
                            <th>R</th>
                            <th>Reason</th>
                        </tr>

                    </thead>
                    <tbody>
                        @foreach (var item1 in componentVM)
                        {
                            @if (item.ServiceCategoryId == item1.ServiceCategogyId)
                            {
                                <tr>

                                    @*@foreach (var InspItem in InspModel)
                                        {*@
                                    <td> <SfTextBox ID="txtLeftFront" Readonly="true" @bind-Value="item1.ComponentName"></SfTextBox></td>
                                    <td><SfTextBox ID="txtThirtyTwoNds" @bind-Value="objIns.ThirtyTwoNds"></SfTextBox></td>
                                    <td><SfTextBox ID="txtPsi" @bind-Value="objIns.Psi"></SfTextBox></td>
                                    <td><SfTextBox ID="txtOk" @bind-Value="objIns.Ok"></SfTextBox></td>
                                    <td><SfTextBox ID="txtS" @bind-Value="objIns.S"></SfTextBox></td>
                                    <td><SfTextBox ID="txtRepair" @bind-Value="objIns.Repair"></SfTextBox></td>
                                    <td><SfTextBox ID="txtReasons" @bind-Value="objIns.Reasons"></SfTextBox></td>
                                    <td><SfTextBox ID="txtNote" @bind-Value="objIns.Note"></SfTextBox></td>

                                </tr>
                            }
                        }

                    </tbody>
                </table>
            </div>

        }
    </div>
    <div class="row">
        <div class="col-md-4">
            <div class="form-group">
                <button type="submit" class="btn btn-primary">Save</button>
                <button type="submit" class="btn btn-primary" @onclick="@(() => Cancel())">Cancel</button>
            </div>
        </div>
    </div>
</EditForm>

    @code {
        public string flag { get; set; }
        public List<ServiceCategory> objServiceCateList { get; set; }
        public List<ComponentVM> componentVM { get; set; }

        // public InspModel objIns = new InspModel();
        public InspectionForm objIns = new InspectionForm();


        protected override void OnInitialized()
        {
            objServiceCateList = CategoryService.GetAllCategory();
            componentVM = ComponentService.GetComponents();
        }

        public class InspModel
        {
            public List<InspectionForm> InspList { get; set; }
        }

        protected void CreateInspection()
        {

        }

        void Cancel()
        {

        }

    }

 

  • 1

    I may be misunderstanding what you're doing, but it looks like you're binding to the same object, so the fields are going to display the same value. Here's a very basic example that might help. I duplicate what it sounds like you're experiencing and another way to set it up.

    @page "/"
    
    @if(model != null)
    {
        <EditForm Model="model">
            <h2>Binding to same object in model</h2>
            @for (var i = 0; i < 5; i++)
            {
                <p><InputText @bind-Value="model.Foo"></InputText></p>
            }
    
            <h2>Binding to list of objects</h2>
            @foreach (var item in model.BazList)
            {
                <p><InputText @bind-Value="item.Foobar"></InputText></p>
            }
        </EditForm>
    }
    
    @code {
            SomeModel model = new SomeModel()
            {
                BazList = new List<SomeSubModel>()
                {
                    new SomeSubModel { Foobar = "" },
                    new SomeSubModel { Foobar = "" },
                    new SomeSubModel { Foobar = "" },
                }
            };
    
        public class SomeModel
        {
            public string Foo { get; set; }
            public string Bar { get; set; }
            public List<SomeSubModel> BazList { get; set; }
        }
    
        public class SomeSubModel
        {
            public string Foobar { get; set; }
        }
    }
    Posted 3 years ago by selliott Edited 3 years ago
  • 0

    Thanks for reply. In the above Code, It will generate the 5 textbox. but  @bind-Value="model.Foo" will same for all the 5 texbox, so if we will change for one textbox, it will change in all 5 textbox due to two way binding features. How can i make as unique Id for each textbox. So that user will be able to enter 5 different text value in all 5 textbox. 

    Posted 3 years ago by chandraev
  • 0

    That's why I added the second part of the example (Binding to a list of objects), to show a way to add unique entries. You're going to need to do something like add the InspectionForm object into ComponentVM maybe, then bind to item1.ObjIns.ThirtyTwoNds. It's difficult for me to say without working with it, but that's the general idea.

    Posted 3 years ago by selliott
  • 0

    This might be a better example to show the general idea

    @page "/"
    
    @if(model != null)
    {
        <EditForm Model="model">
            <h2>Binding to list of objects</h2>
            <table>
            @foreach (var item in model.BazList)
            {
                <tr>
                    <td><InputText @bind-Value="item.Foobar"></InputText></td>
                    <td><InputText @bind-Value="item.Foobar2"></InputText></td>
                    <td><InputText @bind-Value="item.Foobar3"></InputText></td>
                    <td><InputText @bind-Value="item.Foobar4"></InputText></td>
                    <td><InputText @bind-Value="item.Foobar5"></InputText></td>
                    <td><InputText @bind-Value="item.Foobar6"></InputText></td>
                </tr>
            }
            </table>
        </EditForm>
    }
    
    @code {
        SomeModel model = new SomeModel
        {
            BazList = new List<BazModel>()
            {
                new BazModel(),
                new BazModel(),
                new BazModel(),
                new BazModel()
            }
        };
    
        public class SomeModel
        {
            public string Foo { get; set; }
            public string Bar { get; set; }
            public List<BazModel> BazList { get; set; }
        }
    
        public class BazModel
        {
            public string Foobar { get; set; }
            public string Foobar2 { get; set; }
            public string Foobar3 { get; set; }
            public string Foobar4 { get; set; }
            public string Foobar5 { get; set; }
            public string Foobar6 { get; set; }
        }
    }
    Posted 3 years ago by selliott Edited 3 years ago
  • 0

    Thanks for reply. The given above code is working fine for one entry section. If my requirement is for multiple entry section like given below code, how can we do ?

     @page "/counter"
    
    
    @if (model != null)
    {
    <EditForm Model="model">
    
        <h2>First Entry Section</h2>
        @foreach (var item in model.BazList)
        {
            <p><InputText @bind-Value="item.Foobar"></InputText></p>
            <p><InputText @bind-Value="item.Foobar1"></InputText></p>
            <p><InputText @bind-Value="item.Foobar2"></InputText></p>
        }
        <h2>Second Entry Section</h2>
        @foreach (var item in model.BazList)
        {
            <p><InputText @bind-Value="item.Foobar"></InputText></p>
            <p><InputText @bind-Value="item.Foobar1"></InputText></p>
            <p><InputText @bind-Value="item.Foobar2"></InputText></p>
        }
        <h2>Third Entry Section</h2>
        @foreach (var item in model.BazList)
        {
            <p><InputText @bind-Value="item.Foobar"></InputText></p>
            <p><InputText @bind-Value="item.Foobar1"></InputText></p>
            <p><InputText @bind-Value="item.Foobar2"></InputText></p>
        }
    </EditForm>
    }
    
    @code {
        SomeModel model = new SomeModel()
        {
            BazList = new List<SomeSubModel>()
            {
               new SomeSubModel(),
            }
        };
    
        public class SomeModel
        {
            public string Foo { get; set; }
            public string Bar { get; set; }
            public List<SomeSubModel> BazList { get; set; }
        }
    
        public class SomeSubModel
        {
            public string Foobar { get; set; }
            public string Foobar1 { get; set; }
            public string Foobar2 { get; set; }
        }
    }
    Posted 3 years ago by chandraev
  • 0

    I imagine you'll need to add another object named something like Sections, which could be something like List<Section>, and BazList would need moved into Section.

    Posted 3 years ago by selliott Edited 3 years ago
  • 0

    Yes, Thanks for giving me this idea.  It looks like this will fix the issue.

    Posted 3 years ago by chandraev
  • 0

    I did like given below code, But not working as expected, any suggestion on this ?

    @page "/counter"
    
    @if (model != null)
    {
    <EditForm Model="model">
    
        <h2>First Entry Section</h2>
        @foreach (var item in model.SectList)
        {
            foreach (var item1 in item.BazList)
            {
                <p><InputText @bind-Value="item1.Foobar"></InputText></p>
                <p><InputText @bind-Value="item1.Foobar1"></InputText></p>
                <p><InputText @bind-Value="item1.Foobar2"></InputText></p>
            }
    
            foreach (var item1 in item.BazList)
            {
                <p><InputText @bind-Value="item1.Foobar"></InputText></p>
                <p><InputText @bind-Value="item1.Foobar1"></InputText></p>
                <p><InputText @bind-Value="item1.Foobar2"></InputText></p>
            }
        }
    
    </EditForm>
    }
    
    @code {
    
        SectionModel model = new SectionModel()
        {
            SectList = new List<SomeModel>()
            {
                new SomeModel()
                {
                  BazList=new List<SomeSubModel>()
                  {
                      new SomeSubModel(),
                  }
                }
            },
        };
    
        public class SectionModel
        {
            public List<SomeModel> SectList { get; set; }
        }
    
        public class SomeModel
        {
            public string Foo { get; set; }
            public string Bar { get; set; }
            public List<SomeSubModel> BazList { get; set; }
        }
    
        public class SomeSubModel
        {
            public string Foobar { get; set; }
            public string Foobar1 { get; set; }
            public string Foobar2 { get; set; }
        }
    }
    Posted 3 years ago by chandraev
  • 0
    @page "/counter"
    
    @if (model != null)
    {
        <EditForm Model="model" OnValidSubmit="HandleValidSubmit">
            <h1>@model.Foo</h1>
            <p>@model.Bar</p>
            @foreach (var item in model.SectList)
            { 
                <h2>@item.SectionTitle</h2>
                @foreach (var item1 in item.BazList)
                {
                    <p><InputText @bind-Value="item1.Foobar"></InputText></p>
                    <p><InputText @bind-Value="item1.Foobar1"></InputText></p>
                    <p><InputText @bind-Value="item1.Foobar2"></InputText></p>
                }
            }
            <button>Submit</button>
        </EditForm>
    
        <p>
            @submittedDataString
        </p>
    }
    
    @code {
        string submittedDataString;
    
        SomeModel model = new SomeModel
        {
            Foo = "Some title or something",
            Bar = "Some other details",
            SectList = new List<SectionModel>
            {
                new SectionModel
                {
                    SectionTitle = "Section 1",
                    BazList=new List<BazModel>
                    {
                        new BazModel(),
                    }
                },
                new SectionModel
                {
                    SectionTitle = "Section 2",
                    BazList=new List<BazModel>
                    {
                        new BazModel(),
                    }
                },
                new SectionModel
                {
                    SectionTitle = "Section 3",
                    BazList=new List<BazModel>
                    {
                        new BazModel(),
                    }
                },
            }
        };
    
        void HandleValidSubmit()
        {
            // Simply just serializing this to display the example data on the page
            submittedDataString = System.Text.Json.JsonSerializer.Serialize(model);
        }
    
        public class SomeModel
        {
            public string Foo { get; set; }
            public string Bar { get; set; }
            public List<SectionModel> SectList { get; set; }
        }
    
        public class SectionModel
        {
            public string SectionTitle { get; set; }
            public List<BazModel> BazList { get; set; }
        }
    
        public class BazModel
        {
            public string Foobar { get; set; }
            public string Foobar1 { get; set; }
            public string Foobar2 { get; set; }
        }
    }
    Posted 3 years ago by selliott Edited 3 years ago
  • 0

    @selliott,  Thanks for sharing the working code snippet. I took some approach to finish this task. I took the synfussion  Grid Control and generated the required tabular row similar to asp.net webform Gridview. 

    Posted 3 years ago by chandraev
Someone is typing...

Post a Reply

You must be logged in to add a new post.
Number of online users: 0
An error has occurred. This application may no longer respond until reloaded. Reload 🗙