ASP.NET Control的GetElementById保持返回'null'

时间:2011-07-22 00:08:51

标签: javascript asp.net dom controls getelementbyid

我非常绝望地花了一个多小时试图解决这个问题。我试图访问从ASP.NET控件创建的DOM中的节点。我正在使用完全相同的ID,我可以看到它们在页面呈现后查看HTML源代码时匹配。这是我的[MODIFIED根据建议,但仍然没有工作]代码:

ASP.NET标头

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
    <script type="text/javascript">
    $(document).ready(
        var el = document.getElementById('<%= txtBox.ClientID %>');
        el.onchange = alert('test!!');
    )
    </script>
</asp:Content>

ASP.NET Body

<asp:TextBox ID="txtBox" runat="server"></asp:TextBox>

结果Javascript&amp;上面的HTML

<script type="text/javascript">
$(document).ready(
    var el = document.getElementById('MainContent_txtBox');
    el.onchange = alert('test!!');
)
</script>
...
<textarea name="ctl00$MainContent$txtBox" id="MainContent_txtBox"></textarea>

我只能假设脚本在控件ID解析之前加载,但是当我使用Chrome的“Inspect Element”功能查看时间轴时,似乎并非如此。当我创建一个常规的textarea框来测试和实现相同的代码(当然是不同的id)时,会触发警告框。

我到底想念的是什么?这让我疯狂&gt;。&lt;

编辑:可行的Wierd代码,但仅限于初始页面加载;点燃onload而不是onchange。即使是jQuery,也说明。现在显然无法正常工作。唉!!

$(document).ready(function() {
    document.getElementById('<%= txtBox.ClientID %>').onchange = alert('WORKING!');
})

3 个答案:

答案 0 :(得分:5)

假设呈现的标记确实以该顺序出现,问题是在JavaScript尝试找到它时该元素尚不存在。

将JS移动到元素下方(最好是在正文末尾)或将其包裹在jQuery's document ready event handler之类的内容中。

<强>更新

为了回应您的编辑,您几乎就在那里,但(正如其他人提到的那样)您需要为onchange事件分配一个函数,而不是alert()的返回结果。像这样:

$(document).ready(function() {
  // Might as well use jQuery to attach the event since you're already using
  //  it for the document ready event.
  $('#<%= txtBox.ClientID %>').change(function() {
    alert('Working!');
  });
});

通过编写onchange = alert('Working');,您要求JavaScript将alert()方法的结果分配给onchange属性。这就是为什么它在页面加载时立即执行它,但实际上从未实际响应onchange事件(因为你没有指定一个函数来运行onchange)。

答案 1 :(得分:2)

拿起jQuery。

然后你可以

$(function()
{
    var el = document.getElementById('<%= txtBox.ClientID %>');
    el.onclick() { alert('test!!'); }
});

答案 2 :(得分:1)

其他答案指出了错误(试图在DOM节点进入文档之前访问它们),我只想指出替代解决方案。

简单方法

在要访问的元素的结束标记下面的HTML中添加脚本元素。以最简单的形式,将它放在关闭身体标签之前。此策略还可以使页面显示得更快,因为浏览器不会暂停为脚本加载HTML。整体加载时间是相同的,但脚本仍然需要加载执行,只是这个顺序使得看起来对用户来说更加苛刻。

使用window.onload或&lt; body onload =“...”...&gt;

每个浏览器都支持此方法,但在加载所有内容后会触发此方法,因此页面可能会在短时间内显示为非活动状态(如果加载分析,则可能很长时间)。但它非常强大。

使用DOM就绪功能

其他人建议使用jQuery,但您可能不希望4,000行和90kb代码仅用于DOM就绪功能。 jQuery非常复杂,很难从库中删除。然而,大卫马克的MyLibrary是非常模块化的,很容易提取你想要的位。代码质量也非常出色,至少与其他任何库相同。

以下是从MyLibrary中提取的DOM就绪函数的示例:

var API = API || {};

(function(global) {

  var doc = (typeof global.document == 'object')? global.document : null;

  var attachDocumentReadyListener, bReady, documentReady,
      documentReadyListener, readyListeners = [];
  var canAddDocumentReadyListener, canAddWindowLoadListener,
      canAttachWindowLoadListener;

  if (doc) {
    canAddDocumentReadyListener = !!doc.addEventListener;
    canAddWindowLoadListener    = !!global.addEventListener;
    canAttachWindowLoadListener = !!global.attachEvent;

      bReady = false;
      documentReady = function() { return bReady; };
      documentReadyListener = function(e) {
        if (!bReady) {
          bReady = true;
          var i = readyListeners.length;
          var m = i - 1;
          // NOTE: e may be undefined (not always called by event handler)
          while (i--) { readyListeners[m - i](e); }
        }
      };

      attachDocumentReadyListener = function(fn, docNode) {
        docNode = docNode || global.document;
        if (docNode == global.document) {
          if (!readyListeners.length) {
            if (canAddDocumentReadyListener) {
              docNode.addEventListener('DOMContentLoaded',
                                        documentReadyListener, false);
            }
            if (canAddWindowLoadListener) {
              global.addEventListener('load', documentReadyListener, false);
            }
            else if (canAttachWindowLoadListener) {
              global.attachEvent('onload', documentReadyListener);
            } else {
              var oldOnLoad = global.onload;              
              global.onload = function(e) { 
                  if (oldOnLoad) { 
                    oldOnLoad(e); 
                  }
                  documentReadyListener();
              };
            }
          }
          readyListeners[readyListeners.length] = fn;
          return true;
        }
        // NOTE: no special handling for other documents
        // It might be useful to add additional queues for frames/objects
        else {
          if (canAddDocumentReadyListener) {
            docNode.addEventListener('DOMContentLoaded', fn, false);
            return true;
          }
          return false;
        }
      };

      API.documentReady = documentReady;
      API.documentReadyListener = documentReadyListener;
      API.attachDocumentReadyListener = attachDocumentReadyListener;

  }
}(this));

将它用于您的案例:

function someFn() {
  var el = document.getElementById('MainContent_txtBox');
  el.onclick = function() { alert('test!!');
}

API.attachDocumentReadyListener(someFn);

或者可以提供匿名函数:

API.attachDocumentReadyListener(function(){
  var el = document.getElementById('MainContent_txtBox');
  el.onclick = function() { alert('test!!');
};

非常简单的DOM就绪函数可以在10行代码中完成,如果你只想要一个特定的情况,但当然它们不那么健壮,不能重复使用。