0

I have a client-side Javascript I use in an ASP.NET page to set the visibility of a couple of items in a datalist. Basically, when item 1 is visible, item 2 should be hidden and vice-versa. This code also enables/disables some ASP.NET required field validators depending on the visibility of the fields around them on the client side.

The code works fine unless I have an ASP.NET validation error. When the validation fails, the fields reset to their default visibility (hidden).

I've ruled out this being a postback since my server-side breakpoints don't get hit when the problem occurs. This seems to be something with the client-side script.

Server-side fixes are out since the page never posts back. I'm wondering how I can do this from a Javascript perspective? Is there a way to fire custom code when the validation scripts fire?

I thought about using a cookie, but I don't think that will help me unless I can hook into the validation event.

Code follows...

function handleDropDown(e, a, b, c, v1, v2, h1, h2) {
    var i = parseInt(c) + 2;
    var x = parseInt(c) + 3;

    if (e.value == "Yes") {
        document.getElementById(i).style.display = "inline";
        document.getElementById(i).style.visibility = "visible";

        document.getElementById(x).style.display = "none";
        document.getElementById(x).style.visibility = "hidden";

        document.getElementById(a).focus();

        //Enable validator if needed
        var oVal1 = document.getElementById(v1);
        var oVal2 = document.getElementById(v2);

        var oVis1 = document.getElementById(h1);
        var oVis2 = document.getElementById(h2);

        ValidatorEnable(oVal1, true);
        if (oVis1 != null) {
            oVis1.value = "true";
        }
        ValidatorEnable(oVal2, false);
        if (oVis2 != null) {
            oVis2.value = "false";
        }
       }
    else if (e.value == "No") {
        document.getElementById(x).style.display = "inline";
        document.getElementById(x).style.visibility = "visible";

        document.getElementById(i).style.display = "none";
        document.getElementById(i).style.visibility = "hidden";

        document.getElementById(b).focus();

        //Enable validator if needed
        var oVal1 = document.getElementById(v1);
        var oVal2 = document.getElementById(v2);

        var oVis1 = document.getElementById(h1);
        var oVis2 = document.getElementById(h2);

        ValidatorEnable(oVal1, false);
        if (oVis1 != null) {
            oVis1.value = "false";

        }
        ValidatorEnable(oVal2, true);
        if (oVis2 != null) {
            oVis2.value = "true";
        }
    }
}

ASPX Markup snippet: **

             <span id="spTxtAnswer" class="required" visible="false" runat="server">*</span>
                        <asp:TextBox ID="txtAnswer" Text='<%# Bind("Answer") %>' runat="server" 
                                   TextMode="MultiLine" Height="76px" MaxLength="2000" Width="370px" Visible="false"  >
                        </asp:TextBox>
                        <asp:RequiredFieldValidator ID="valTextBox" ErrorMessage="This question is required." Enabled="false"
                        Display="Static" ControlToValidate="txtAnswer" runat="server" ValidationGroup="Request" />
                        <asp:RequiredFieldValidator ID="valAnswer" ControlToValidate="txtAnswer" ErrorMessage="<br />Other description is required."
                        Display="Static" enabled="false" runat="server"  ValidationGroup="Request" />
                        <span id="spDdlAnswer" class="required" visible="false" runat="server">*</span>
                        <asp:DropDownList ID="ddlAnswer" Visible="false" runat="server" />
                        <asp:RequiredFieldValidator ID="valDropDown" ControlToValidate="ddlAnswer" Enabled="false"
                        ErrorMessage="This field is required." Display="Static" runat="server"
                         InitialValue="(Select)"  ValidationGroup="Request" />
                        <asp:HiddenField ID="hfQuestionID" Value='<%# Bind("QuestionID") %>' runat="server" />
                        <asp:HiddenField ID="hfAnswer" Value='<%# Bind("Answer") %>' runat="server" />
                        <asp:HiddenField ID="hfRequired" Value='<%# Bind("Required") %>' runat="server" />
                        <asp:HiddenField ID="hfVisible" Value="false" runat="server" />

CodeBehind snippet:

TextBox tb1 = (TextBox)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 1].FindControl("txtAnswer");
            TextBox tb2 = (TextBox)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 2].FindControl("txtAnswer");
            RequiredFieldValidator rfv1 = (RequiredFieldValidator)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 1].FindControl("valTextBox");
            RequiredFieldValidator rfv2 = (RequiredFieldValidator)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 2].FindControl("valTextBox");
            HiddenField hf1 = (HiddenField)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 1].FindControl("hfVisible");
            HiddenField hf2 = (HiddenField)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 2].FindControl("hfVisible");

            ddl.Attributes.Add("onchange", "handleDropDown(this,'" + tb1.ClientID + "','" + tb2.ClientID + "','" + questionID + "','" + rfv1.ClientID + "','" + rfv2.ClientID + "'," + 
                "'" + hf1.ClientID + "','" + hf2.ClientID + "');");

            //When selected and viewing in edit mode, set the visibility during page load
            string script = "<script language='javascript'>";
            script += System.Environment.NewLine + "var el = document.getElementById('" + ddl.ClientID + "');";
            script += System.Environment.NewLine + "handleDropDown(el,'" + tb1.ClientID + "','" + tb2.ClientID + "','" + questionID + "','" + rfv1.ClientID + "','" + rfv2.ClientID + "');</script>";
            ClientScript.RegisterStartupScript(Page.GetType(),"startScript", script);

**

4

3 に答える 3

0

私はこれが古いことを知っていますが、他の誰かが私と同じようにこれに出くわした場合に備えて、Cookie を使用してクライアント側とサーバー側の間で状態を追跡するというティムの答えに代わるものを提供したかったのです。

Cookie を使用するのではなく、特定のコントロールがクライアント側で表示/非表示にされているかどうかなど、値を読み取れるようにする必要がある JavaScript がある場合は、同じ方法で独自のビュー ステートを作成することをお勧めします。 .NET はそうです。

私は何年にもわたって多くの同僚が非表示のフィールド コントロールをページ マークアップに挿入しようとしているのを見てきましたが、.NET はビューステートをリロードするときにクライアント側の値を上書きする可能性があるため、常に信頼できるとは限りません。私が使用するソリューションは非常に確実に機能するようで、セットアップも難しくありません。これは、Web ユーザー コントロールやサーバー コントロールでもまったく同じように機能します。これにより、サーバー側とクライアント側がポストバック全体で値にアクセスできるようになり、発生する可能性のある値に対するクライアント側の変更が尊重されます。

以下の私の例は、ブール値、整数、および文字列を示していますが、「文字列」値との間でシリアル化および逆シリアル化できる任意のデータ型で同じメソッドを使用できます。

public partial class MyPage : System.Web.UI.Page
{
    const string
        hdnFld1Nm = "hdnFld1",
        hdnFld2Nm = "hdnFld2",
        hdnFld3Nm = "hdnFld3";

    protected bool HiddenFieldValue1
    {
        get
        {
            object vsVal = this.ViewState["HiddenFieldValue1"];
            if (vsVal == null)
                return false;   // Whatever you want the 'default' value to be.
            else return (bool)vsVal;
        }
        set { this.ViewState["HiddenFieldValue1"] = value; }
    }
    protected int HiddenFieldValue2
    {
        get
        {
            object vsVal = this.ViewState["HiddenFieldValue2"];
            if (vsVal == null)
                return -1;  // Again, default value.
            else
                return (int)vsVal;
        }
        set { this.ViewState["HiddenFieldValue2"] = value; }
    }
    protected string HiddenFieldValue3
    {
        get { return (string)this.ViewState["HiddenFieldValue3"]; }
        set { this.ViewState["HiddenFieldValue3"] = value; }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        // For the boolean state, we'll consider any value other than "0" or NULL to be "true".
        this.HiddenFieldValue1 = (!string.IsNullOrEmpty(this.Request[hdnFld1Nm]) && this.Request.Form[hdnFld1Nm] != "0");

        // For the integer, we have to parse from the string value we get from the Form collection, and deal with the potential for "null" if no value was returned.
        string sHdnVal2 = this.Request.Form[hdnFld2Nm];
        int iHdnVal2;
        if (!string.IsNullOrEmpty(sHdnVal2) && !int.TryParse(sHdnVal2, out iHdnVal2))
            this.HiddenFieldValue2 = iHdnVal2;

        // Getting a string value back is easy.
        this.HiddenFieldValue3 = this.Request[hdnFld3Nm];
    }
    protected void Page_PreRender(object sender, EventArgs e)
    {
        // Before the page actually renders, we want to let the .NET page renderer know that we want these three hidden field values written to the output page.
        this.Page.ClientScript.RegisterHiddenField(hdnFld1Nm, this.HiddenFieldValue1 ? "1" : "0");  // Make sure you keep your boolean logic the same.
        this.Page.ClientScript.RegisterHiddenField(hdnFld2Nm, this.HiddenFieldValue2.ToString());   // Hidden fields can only store "string" values, so we have to "ToString" our int.
        this.Page.ClientScript.RegisterHiddenField(hdnFld3Nm, this.HiddenFieldValue3);
    }
}
于 2015-06-12T16:55:40.893 に答える
0

別のスタックオーバーフローの問題から ( https://stackoverflow.com/a/11723794/704879 ):

「これが問題です: バリデーターがページに読み込まれると、クライアント側の検証をサポートするために少しの JavaScript が作成されます。デフォルトでは表示されないユーザーコントロール内にバリデーターを配置し、このユーザーコントロールが更新パネルにある場合、それはそのjavascriptを適切に作成しません.これが解決策です: updatepanelの外で、私は上記のように、ダミーの検証グループを使用してダミーのテキストボックスを持つダミーのバリデータを作成します:

クレジットは、ソリューションの元のポスター (Anton Belev) に送られます。

于 2013-09-06T19:02:41.410 に答える
0

クライアント側のスクリプトと Cookie を使用して可視性を設定する必要がありました。ポストバック後に値を保持する必要がありますが、クライアント側で読み取る必要があるため、この場合、viewstate は実際にはオプションではありませんでした。

別の関連する問題は、スクリプトを呼び出して IE10 でフィールドの可視性を設定しようとすると、本文の読み込みが完了する前に常に実行されることでした。マスター ページの body タグに呼び出しを設定しましたが、現在は正常に動作しています。

于 2013-09-10T18:32:31.150 に答える