开发者

Elements keeping original values in jQuery objects after PostBack

I am using ASP.NET 3.5 combined with the atrocious UpdatePanel, jQuery.delegate(), and JavaScript object literals.

I use jQuery.delegate() to persist the event handlers, which do get triggered after the PostBack, as expected.

The issue is with the jQuery objects stored in object literal properties on init() where they keep the values they had prior to the ASP.NET PostBack.

Here is my JavaScript :

SFAIC


SFAIC = 
{
    masterPages: { cs: "CS_", cp: "CP_" },
    contentPages: { cs: "CSContent_", cp: "CPContent_" },
    
    isSecurePage  : false,

    $body         : undefined,
    $container    : undefined,
    $updatePanel  : undefined,

    $textBox      : undefined,
    $errorLabel   : undefined
};

SFAIC.init()


SFAIC.init = function () 
{ 
    log( "--> SFAIC.init() fired" );

    var self = this; 

    self.$body        = $( "body" );
    self.$container   = self.$body.find( "#container" );
    self.$updatePanel = self.getCSMasterElement( "UpdatePanel1", self.$container );
    self.$textBox     = self.getContentElement( "TextBox1" );
    self.$errorLabel  = self.getContentElement( "ErrorLabel1" );
     
    self.$updatePanel.delegate( self.$textBox.selector, "blur", function () 
    { 
       self.validateRequired( self.$textBox, self.$errorLabel ); 
    });
    
    self.$textBox.focus();
};

SFAIC.validateRequired()


SFAIC.validateRequired = function ( $element, $errorLabel ) 
{
    if ( $element.val().length === 0 ) { $errorLabel.text( "Required" ); }
    else { $errorLabel.text( "" ); }
};


Given the above, when SFAIC.init() is fired, self.textBox is assigned to its jQuery object. I guess herein lies my confusion. I thought that when you call .val(), it would return the value of what's in that element right then. In the case where you make a call to the server and change the value of the control which then comes back rendering the changed value of the element, it seems that the jQuery object doesn't know about that change?

Am I wrong here?

What do I need to do to keep a real-time reference to the element, so that I can get the current value after the page is posted back?

Edit request per @DaveLong :

SFAIC.getCSMasterElement()


SFAIC.getCSMasterElement = function ( id, $context ) 
{ 
    return SFAIC.getElement( SFAIC.masterPages.cs, id, $context ); 
};

SFAIC.getCPMasterElement()


SFAIC.getCPMasterElement = function ( id, $context ) 
{ 
    return SFAIC.getElement( SFAIC.masterPages.cp, id, $context ); 
};

SFAIC.getContentElement()


SFAIC.getContentElement = function ( id, $context ) 
{ 
    return SFAIC.getElement
    ( 
        ( SFAIC.isSecurePage )开发者_运维问答 ? SFAIC.contentPages.cp : SFAIC.contentPages.cs, 
        id, 
        $context 
    ); 
};

SFAIC.getElement()


SFAIC.getElement = function ( page, id, $context ) 
{
    selector = SFAIC.getElementIdSelector( page, id );
    
    return ( selector ) 
        ? ( $context && $context.length ) 
            ? $context.find( selector ) 
            : SFAIC.$body.find( selector )
        : undefined;
};

SFAIC.getElementIdSelector()


SFAIC.getElementIdSelector = function ( page, id ) 
{ 
    var prefix = SFAIC.getElementPrefix( page );
    return ( prefix && id ) ? "#" + prefix + id : undefined;
};

SFAIC.getElementPrefix()


SFAIC.getElementPrefix = function ( page ) 
{   
    switch ( page ) 
    {
        case SFAIC.masterPages.cs : return SFAIC.masterPages.cs;
        case SFAIC.masterPages.cp : return SFAIC.masterPages.cp + SFAIC.masterPages.cs;
        case SFAIC.contentPages.cs : return SFAIC.masterPages.cs + SFAIC.contentPages.cs;
        case SFAIC.contentPages.cp : return SFAIC.masterPages.cp + SFAIC.masterPages.cs + SFAIC.contentPages.cs + SFAIC.contentPages.cp;                
    }
};


The UpdatePanel removes the entire target from the DOM and replaces it with new markup from the response. It isn't that your vars are holding old values, it is that they are holding references to the original markup. You need to "reinitialize" in order to obtain references to the new nodes in the DOM.


maybe you should re-init the objects when the ajax updatepanel request completes

<script type="text/javascript" language="javascript">
     Sys.WebForms.PageRequestManager.getInstance().add_endRequest(ReInitiate); 
     function ReInitiate(sender, args)
     {
        //re-initialize the objects 
        //add code here 
     } 
</script>

Cheers, Nitin


For what it's worth, the solution I came up with was a customized version of Paul Irish's Markup-based unobtrusive comprehensive DOM-ready execution and @NitinJS' / @Ethan's answers.


At the bottom of my JavaScript I added:

UTIL = {

    fire : function(func, funcname) {

        var namespace = SFAIC;
        funcname = (funcname === undefined) ? "init" : funcname;

        if (func !== "" && 
            namespace[func] && 
            typeof namespace[func][funcname] == "function") { 

            namespace[func][funcname](); 

        }

    },

    loadEvents : function() {

        var bodyId = document.body.id;

        UTIL.fire("common");
        UTIL.fire(bodyId);

    }

};

// Fire events on initial page load.
UTIL.loadEvents();

// Fire events for partial postbacks.
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(UTIL.loadEvents);


In my MasterPage's aspx, I modified the body tag to:

<body id="<%=bodyId%>">


In my MasterPage's code-behind declarations, I added:

Public bodyId As String = String.Empty


In my MasterPage's code-behind Page.PreRender handler, I added:

bodyId = MyBase.GetType.BaseType.Name
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜