0

I am trying to create a web form where a user uses some drop down information and then a container appears and the user has to select one of the two radio options OK or NOT OK.

The web form is created dynamically using asp:placeholder in the frontend. So the number of placeholders which will come depends on the entries in database.

So lets assume 5 images with buttons pop up, the user needs to select at least 1 button per container and also for any container if the user selects a NOT OK, the value should go as 1 in DB. I have tried 3-4 options but none of them seem to work.

How it is grouped in the generateLayout method

Frontend try

How I did the recursive option.

TIA

I have tried using radio.attributes, tried using Javascript in the front end, using a recursive control method for radios. Nothing seems to work.

int status = hiddenStatus.Value == "1" ? 1 : 0;

string groupName = toolName;

RadioButton okButton = new RadioButton
        {
            ID = "RadioButtonOk_" + toolName,
            CssClass = "RadioButtonOk",
            GroupName = groupName,
            Text = "OK"
        };

okButton.Attributes.Add("data-tool", toolName);

RadioButton nokButton = new RadioButton
        {
            ID = "RadioButtonNok_" + toolName,
            CssClass = "RadioButtonNok",
            GroupName = groupName,
            Text = "NOK"
        };
nokButton.Attributes.Add("data-tool", toolName);

Panel okPanel = new Panel { CssClass = "radio-button-wrapper" };
okPanel.Controls.Add(okButton);

Panel nokPanel = new Panel { CssClass = "radio-button-wrapper" };
nokPanel.Controls.Add(nokButton);

Panel radioPanel = new Panel { CssClass = "radio-buttons" };
radioPanel.Controls.Add(okPanel);
radioPanel.Controls.Add(nokPanel);

Panel detailsPanel = new Panel { CssClass = "tool-details" };
detailsPanel.Controls.Add(toolNameLabel);
detailsPanel.Controls.Add(header);
detailsPanel.Controls.Add(description);
detailsPanel.Controls.Add(radioPanel);

groupPanel.Controls.Add(image);
groupPanel.Controls.Add(detailsPanel);

ToolContainer.Controls.Add(groupPanel);


<script type ="text/javascript">
function validateInspection() {
    var toolGroups = {};
    var radios = document.querySelectorAll("input[type='radio']");
    var nokSelected = false;

    for (var i = 0; i < radio.length; i++) {
        var group = radios[i].getAttribute("data-tool");
        if (!group) continue;

        if (!toolGroups[group]) {
            toolGroups[group] = { ok: false, nok: false, selected: false };
        }
        if (radios[i].checked) {
            toolGroups[group].selected = true;
            if (radios[i].value.toUpperCase() == "NOK" || radios[i].id.toUpperCase().indexOf("NOK") !== -1) {
                nokSelected = true;
            }
        }
    }
}

var allSelected = true;
for (var key in toolGroups) {
    if (!toolGroups[key].selected) {
        allSelected = false;
        break;
    }
}

if (!allSelected) {
    alert("Please select OK or NOK for every tool");
    return false;
}

var statusField = document.getElementById("<%= hiddenStatus.ClientID %>");
if (statusField) {
    statusField.value = nokSelected ? "1" : "0";
}
return true;
}
</script>
5
  • 1
    Welcome to Stack Overflow. To help you properly please don't use Screenshots of your Code instead post them in your question with a formatting to a codeblock as you did in your last line. This ensures that we don't miss any special hidden characters and it maintains the question as a whole without requiring to open 4 Tabs just to understand what is going on. Commented Apr 10 at 7:15
  • Thank you. Yes, I just changed it and added the code. Commented Apr 10 at 7:26
  • Are you using. Net framework 4.8, and asp.net webforms, or are you using a .net core project? Commented Apr 11 at 1:07
  • Yes @AlbertD.Kallal, I am using 4.8 and webforms. Commented Apr 11 at 7:45
  • Ok, so you should remove the core tag, since you using .net framework, not .net core. And you could add the asp.net tag. Regardless, see my answer below as to how one approaches such tasks with webforms..... Commented Apr 11 at 20:53

1 Answer 1

0

First, it makes little sense to try and write code to inject a bunch of controls. And those controls need an "id", and also need for things like view state to be correctly setup.

However, since you want to "repeat" some controls over and over?

Then use a repeater, or even ListView, or even a GridView. That way you can setup and write out the markup one time, and then asp.net will "repeat" the controls automatic over and over. But MORE important is you can then loop those rows and get the value(s) from that row, and send back to the database.

Let's do a simple example. Say I have some survey data. And the survey table looks like this:

enter image description here

And of course to get information about the fighter, we have a table Fighters with columns like this:

enter image description here

So, for layout, we want to repeat the markup for each row. The picture, description, and of course the RadioButton list of choices for rating the fighter.

So, then we have this markup:

        <table class="table table-hover" style="width:80%">
            <thead>
                <tr>
                    <th>Image</th>
                    <th>Fighter</th>
                    <th>Engine</th>
                    <th>Thrust&nbsp;(lbs)</th>
                    <th>Description</th>
                    <th>Your Rating</th>
                </tr>
            </thead>
            <asp:Repeater ID="rSurvey" runat="server">
                <ItemTemplate>
                <tr>
                <td>
                    <asp:Image ID="iPreview" runat="server" Height="68px" Width="149px"
                        ImageUrl='<%# Eval("ImagePath") %>' />
                </td>
                <td><asp:Label ID="Fighter" runat="server" Text='<%# Eval("Fighter") %>' /></td>
                <td><asp:Label ID="Engine" runat="server" Text='<%# Eval("Engine") %>' /></td>
                <td><asp:Label ID="Thrust" runat="server" Text='<%# Eval("Thrust") %>' Width="70px" /></td>
                <td><asp:Label ID="Description" runat="server" Text='<%#Eval("Description") %>' /></td>
                <td>
                   <asp:RadioButtonList ID="rbRating" runat="server" RepeatDirection="Horizontal" 
                        CssClass="rBut"
                        SelectedValue='<%# Eval("Rating") %>'>
                        <asp:ListItem Value="0">No&nbsp;Rating</asp:ListItem>
                        <asp:ListItem Value="1">Poor</asp:ListItem>
                        <asp:ListItem Value="2">Fair</asp:ListItem>
                        <asp:ListItem Value="3">Good</asp:ListItem>
                        <asp:ListItem Value="4">Excellent</asp:ListItem>
                        <asp:ListItem Value="5">5&nbsp;Stars</asp:ListItem>
                    </asp:RadioButtonList>
                </td>
            </tr> 
                </ItemTemplate>
            </asp:Repeater>
        </table>
        <br />
            <asp:Button ID="cmdSave" runat="server" Text="Submit"
                CssClass="btn"
                OnClick="cmdSave_Click"                
                />

So, by using data binding, we can have asp.net "repeat" the controls over and over for us.

The code behind is thus this:

    public partial class Survey : System.Web.UI.Page
    {

        const int UserID = 3;   // hard code user id for testing
        public DataTable rstSurvey;
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                LoadData();
                Session["rstSurvey"] = rstSurvey;
            }
            else
            {
                rstSurvey = (DataTable)Session["rstSurvey"];
            }
        }

        void LoadData()
        {
            string strSQL =
                $@"select tblFighterSurvey.*, Fighter, Engine, Thrust, Description, ImagePath
                from tblFighterSurvey
                left join Fighters on Fighters.id = tblFighterSurvey.Fighter_ID
                where User_ID = {UserID}
                order by tblFighterSurvey.id";

            rstSurvey = General.MyRst(strSQL);
            rstSurvey.TableName = strSQL;
            rSurvey.DataSource = rstSurvey;
            rSurvey.DataBind();


        }

        protected void cmdSave_Click(object sender, EventArgs e)
        {
            // process each row selection back to table

            foreach (RepeaterItem OneRow in rSurvey.Items)
            {
                RadioButtonList rChoice = (RadioButtonList)OneRow.FindControl("rbRating");
                rstSurvey.Rows[OneRow.ItemIndex]["Rating"] = rChoice.SelectedValue;
            }

            // now save table back to database
            string strSQL = "SELECT * FROM tblFighterSurvey";
            using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
            {
                using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
                {
                    SqlDataAdapter daUpdate = new SqlDataAdapter(cmdSQL);
                    SqlCommandBuilder sUpdate = new SqlCommandBuilder(daUpdate);
                    daUpdate.Update(rstSurvey);
                }

            }
        }

Note how we process back the user choices to the table, and then send the table back to the database with one command/update operation.

Hence, the result looks like this:

enter image description here

So, note how little code, how little markup, and yet if we have 3 or 15 rows, the code will still work just fine. And above even includes the code to save/send the data back to the database. And if we return to the page, then it re-loads fine, including that of the RadioButtonList choices being restored correctly.

So, un-like many web based frameworks, asp.net WebForms does not take well to writing code to "inject" a bunch of controls, and the general approach is to adopt one of the data bound controls like a GridView, ListView, or repeater. In fact, for above, I probably would have used a ListView, or even a GridView, but using a repeater worked just fine.

Note also, while we loaded up the data table with a left join (to pull in the information about the item - this case a fighter and image path), we are still able to persist and use that same table to update and save the survey table data back to the one SQL server table.

Also, if you're looking for each of radio buttons to have some image, then we can cook up a approach for that requirement.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.