0

I have a list which the elements can be reordered or dragged out of the list by JQuery sortable function. When the user press save, raises a postback. I need to capture the list, get the ids still inside the list and by order they come int the html. My approach is add the hidden field inside each ul tag, to store the id of the list item, like this

<ul>
   <li>Item1 <input id="itemID" type="hidden" value="1"></li>
   <li>Item2 <input id="itemID" type="hidden" value="2"></li>
...
</ul>

For that i subclass WebControl. At RenderContents method, i render the html as posted.

The problem is how to access the control children on the postback call.

Because the JavaScript change the list, the Viewstate is useless. The property Controls always come empty. Can't find a way to force the parse of the Innerhtml or even get the Innerhtml. What am i missing here?

UPDATE: To clarify, the html posted above is produced by the subclass of webcontrol. Below the code of the server control that i named as MyListControl:

    [ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
    public class MyListControl : WebControl {

        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public  List<String> Itens;



        protected override void RenderContents(HtmlTextWriter output)
        {

            var ul = new HtmlGenericControl("ul");
            int order = 0;
            if (Itens != null)
                foreach (var liText in Itens)
                {
                    var li = new HtmlGenericControl("li");
                    li.InnerText = liText;
                    ul.Controls.Add(li);

                    var input = new HtmlInputHidden() { ID = "Order", Value = order.ToString() };
                    li.Controls.Add(input);
                    order++;
                }
            Controls.Add(ul);
            ul.RenderControl(output);
        }
    }
Because the html is not parsed on post FindControl method can't find anything also.
MiguelSlv
  • 14,067
  • 15
  • 102
  • 169
  • Please see ["Should questions include “tags” in their titles?"](http://meta.stackexchange.com/questions/19190/should-questions-include-tags-in-their-titles), where the consensus is "no, they should not"! –  Jan 22 '16 at 12:41

2 Answers2

0

You won't get the the child controls or the main controls until you put runat="server". Instead of using hidden fields, I suggest you use data attributes like

<li data-id="1"></li>

To find the child controls, you need to run a foreach loop on the parent controls.

 foreach (Control c in parentControlId.Controls)
        { //do something}
skzi
  • 340
  • 3
  • 14
  • I updated the post to clarify some aspects that wasn't very clear. The posted html generated by the server control, so runat="server" tag can't be used here. The control itself already runts at server as long is used with the server tag. The idea of adding data-id looks good. – MiguelSlv Jan 22 '16 at 11:14
0

I was trying the wrong approach. It came back to me that the html is not sended back on post. So there is no way rebuild the control tree based on the response. Obvious ViewState also does not reflect the change on html controls because is only transport control states.

So the only option i see is to use an hidden control to store the list order and send back to the server. The control can be filled by an javascript function.

I add the following html to the page:

<asp:ListView runat="server" ID="lvSortableList">
    <LayoutTemplate>
        <ul id="lvSortableList" class="connectedSortable">
            <li id="itemPlaceholder" runat="server"></li>
        </ul>
    </LayoutTemplate>
    <ItemTemplate>
         <li data-giro="<%# Eval("MyID") %>"><%# Eval("field1") %></li>
    </ItemTemplate>  <!--data-id stores the item id-->
</asp:ListView>
<input type="hidden" id="impNewOrder" runat="server" clientid="impNewOrder" />

Then, to fill the control i create the following function which goes through all items of the list, get the items ids and store them in the order they were found.

function fillFeedbackSource() {
    var IDs = [];
    $('#lvSortableList li').each(function () {       
    IDs.push($(this).data("id"));
    }); 
    $('[clientid=impNewOrder]').val(IDs); //store the ids separated by ','
};

The save button calls the function fillListOrder on click, before the post.

 <asp:Button ID="btbSave" runat="server" Text="Save" OnClientClick="javascript: fillListOrder();" OnClick="btbSave_Click" Visible="false" />

The server can get the new order by parsing the value of impNewOrder server control.

Goto here to get JQuery sortable list control.

MiguelSlv
  • 14,067
  • 15
  • 102
  • 169