ASP.NET Control 的 GetElementById 不断返回“null”;

发布于 2024-11-25 07:42:23 字数 1459 浏览 1 评论 0原文

我花了一个多小时试图解决这个问题,我很绝望。我正在尝试访问 DOM 中从 ASP.NET 控件创建的节点。我使用完全相同的 id,并且在页面渲染后查看 HTML 源代码时可以看到它们是匹配的。这是我的[根据建议修改,但仍然不起作用]代码:

ASP.NET Header

<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>

Resulting Javascript & ASP.NET Header ASP.NET Body Resulting Javascript &从上面的 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 的“检查元素”功能查看时间线时,情况似乎并非如此。当我创建一个常规文本区域框来测试和实现相同的代码(当然不同的 id)时,警报框会触发。

我到底错过了什么?这让我发疯>。<

编辑:奇怪的代码可以工作,但仅在初始页面加载时有效;触发 onload 而不是 onchange。甚至 jQuery 也表示 .ready 显然无法正常工作。啊!!

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

I'm desperate having spent well over an hour trying to troubleshoot this. I am trying to access a node in the DOM which is created from an ASP.NET control. I'm using exactly the same id and I can see that they match up when looking at the HTML source code after the page has rendered. Here's my [MODIFIED according to suggestions, but still not working] code:

ASP.NET Header

<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>

Resulting Javascript & HTML from above

<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>

I can only assume that the script is loading before the control id has been resolved, yet when I look at the timeline with Chrome's "Inspect Element" feature, it appears that is not the case. When I created a regular textarea box to test and implement the identical code (different id of course), the alert box fires.

What on earth am I missing here? This is driving me crazy >.<

EDIT: Wierd code that works, but only on the initial page load; firing onload rather than onchange. Even jQuery says that .ready doesn't work properly apparently. Ugh!!

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

久夏青 2024-12-02 07:42:23

假设渲染的标记确实按该顺序出现,问题是当您的 JavaScript 尝试查找该元素时该元素还不存在。

要么将该 JS 移动到元素下方(最好是在正文的末尾),要么将其包装在 jQuery 的文档准备中事件处理程序

更新:

为了响应您的编辑,您已经差不多完成了,但是(正如其他人提到的)您需要为 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 的函数)。

Assuming the rendered markup does appear in that order, the problem is that the element doesn't yet exist at the time your JavaScript is attempting to locate it.

Either move that JS below the element (preferably right at the end of the body) or wrap it in something like jQuery's document ready event handler.

Update:

In response to your edits, you're almost there but (as others have mentioned) you need to assign a function to the onchange event, not the return result of alert(). Something like this:

$(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!');
  });
});

By writing onchange = alert('Working');, you were asking JavaScript to assign the result of the alert() method to the onchange property. That's why it was executing it immediately on page load, but never actually in response to the onchange event (because you hadn't assigned that a function to run onchange).

泛滥成性 2024-12-02 07:42:23

选择 jQuery。

那么你可以

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

Pick up jQuery.

Then you can

$(function()
{
    var el = document.getElementById('<%= txtBox.ClientID %>');
    el.onclick() { alert('test!!'); }
});
清醇 2024-12-02 07:42:23

其他答案已经指出了错误(尝试在 DOM 节点出现在文档中之前访问它们),我只会指出替代解决方案。

简单方法

在 HTML 中添加脚本元素,位于您要访问的元素的结束标记下方。最简单的形式是将其放在结束正文标记之前。此策略还可以使页面显示得更快,因为浏览器不会暂停加载脚本的 HTML。总体加载时间是相同的,但是脚本仍然需要加载并执行,只是这个顺序让用户感觉更慢。

使用 window.onload 或

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

使用 DOM 就绪函数

其他人建议使用 jQuery,但您可能不希望仅仅为了 DOM 就绪函数就需要 4,000 行和 90kb 的代码。 jQuery 相当复杂,很难从库中删除。然而,David Mark 的 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!!');
};

如果您只需要一个用于特定情况的函数,则可以在 10 行代码中完成非常简单的 DOM 就绪函数,但当然它们的健壮性较差并且可重复使用性较差。

Other answers have pointed out the error (attempting to access DOM nodes before they are in the document), I'll just point out alternative solutions.

Simple method

Add the script element in the HTML below the closing tag of the element you wish to access. In its easiest form, put it just before the closing body tag. This strategy can also make the page appear faster as the browser doesn't pause loading HTML for script. Overall load time is the same however, scripts still have to be loaded an executed, it's just that this order makes it seem faseter to the user.

Use window.onload or <body onload="..." ...>

This method is supported by every browser, but it fires after all content is loaded so the page may appear inactive for a short time (or perhaps a long time if loading is dealyed). It is very robust though.

Use a DOM ready function

Others have suggested jQuery, but you may not want 4,000 lines and 90kb of code just for a DOM ready function. jQuery's is quite convoluted so hard to remove from the library. David Mark's MyLibrary however is very modular and quite easy to extract just the bits you want. The code quality is also excellent, at least the equal of any other library.

Here is an example of a DOM ready function extracted from MyLibrary:

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));

Using it for your case:

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

API.attachDocumentReadyListener(someFn);

or an anonymous function can be supplied:

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

Very simple DOM ready functions can be done in 10 lines of code if you just want one for a specific case, but of course they are less robust and not as reusable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文