【问题标题】:ASP.NET: How to access repeater generated elements from javascript?ASP.NET:如何从 javascript 访问中继器生成的元素?
【发布时间】:2009-01-23 21:16:24
【问题描述】:

我有一系列使用 asp:repeater 生成的行:

<asp:repeater ID="itemsRepeater" 
      OnItemDataBound="itemsRepeater_ItemDataBound" 
      runat="Server">
   <itemtemplate>
      <tr>
         <td>
            <asp:HyperLink ID="linkView" runat="server"
               Text="<%# GetItemText((Item)Container.DataItem) %>" 
               NavigateUrl="<%# GetViewItemUrl((Item)Container.DataItem) %>" />
         </td>
         <td>
            <asp:HyperLink ID="linkDelete" runat="server"
                Text="Delete"
                NavigateUrl="<%# GetDeleteUrl((ActionItem)Container.DataItem) %>" />
         </td>
      </tr>
   </itemtemplate>
</asp:repeater>

转发器创建一个 HTML 表格,每一行都包含一个项目的链接和(本质上是)一个“删除”链接。上面的简化示例代码生成的 HTML 类似于:

<TR>
<TD>
   <A href="ViewItem.aspx?ItemGuid={19a149db-5675-4eee-835d-3d78372ca6f9}">
      AllisonAngle_SoccerGirl001.jpg
   </A>
</TD>
<TD>
   <A href="DeleteItem.aspx?ItemGuid={19a149db-5675-4eee-835d-3d78372ca6f9}">Delete</A>
</TD>
</TR>

现在一切正常,但我想将“删除”转换为客户端。我希望能够单击该链接,它会在客户端 javascript 上:

  • 提示“您确定...”的警报
  • 有 javascript 问题服务器命中以实际删除他们想要的项目
  • 从客户端 DOM 树中删除项目

所以有四个问题需要解决:

  1. 如何将 JavaScript 连接到客户端单击 删除 链接。
  2. 如何知道用户点击了什么项目删除
  3. 防止回发
  4. 删除用户点击的行

这是我的问题。

从这里你会发现我漫无目的的尝试来解决它。不要将以下任何内容视为与任何可能接受的解决方案有任何关系。仅仅因为我在下面发布了代码,并不意味着它是有用的。这并不意味着我在最佳解决方案的距离之内。而且因为我不能让任何事情低于工作 - 它一定走错了路。


我的尝试

连接 Javascript

第一个任务是将删除链接从 HTML 转换为:

<A href="DeleteItem.aspx?ItemGuid={19a149db-5675-4eee-835d-3d78372ca6f9}">
   Delete
</A>

变成更javascripty的东西:

<A href="#" 
      onclick="DeleteItem('DeleteItem.aspx?ItemGuid={19a149db-5675-4eee-835d-3d78372ca6f9}')">
   Delete
</A>

并添加脚本:

<script type="text/javascript">
   //<![CDATA[
       function DeleteItem(deleteUrl)   
       {   
          //Ask the user if they really want to
          if (!confirm("Are you sure you want to delete INSERT NAME HERE?"))
          {
             return false;
          }

          //Call returns false if the server returned anything other than OK
          if (!DoAjaxHit(deleteUrl)
          {
             return false;
          }

          //Remove the table row from the browser
          var tableRow = document.getElementById("TODO-WHAT ID");
          if (row != null)
          {
             //TODO: how to delete the tableRow from the DOM tree?
             //document.Delete(tableRow) ?
          }

          //return false to prevent a postback
          return false;
       }
   //]]>
</script>

可以使用什么 ASP 代码组合来创建上述内容?我听说 asp:LinkBut​​ton 有一个 OnClientClick 事件,您可以在其中连接一个 javascript 函数:

<asp:LinkButton ID="linkDelete" runat="server"
   Text="Delete"
   OnClientClick="DeleteItem(<%# GetDeleteUrl((ActionItem)Container.DataItem) %>);"/>

问题是呈现的 HTML 字面上包含:

<a onclick="DeleteItem(&lt;%# GetDeleteUrl((ActionItem)Container.DataItem)) %>);" ...>
   Delete
</a>

如果我将客户端点击事件处理程序更改为:

   OnClientClick="DeleteItem('todo - figure this out');"/>

它可以工作 - 以及“todo - 解决这个问题”也可以工作。


防止回发

实际上发生了上面的 javascript 调用(我可以看到我的警报),但还有下一个问题:从 javascript 函数返回 false 不会阻止回发。事实上,我可以看到生成的html代码上的href不是“#”,而是

javascript:__doPostBack('ctl0....

我自己尝试更改 ASPX 代码以包含 OnClick 处理程序:

   OnClick="#"
   OnClientClick="DeleteItem('todo - figure this out');"

但编译器认为磅侧是杂注,并抱怨:

预处理器指令必须显示为 第一个非空白字符 一行


表行标识

表格行没有ID,它们是由asp:repeater生成的。

javascript函数如何知道是什么触发了点击事件? javascript 需要能够找到元素,并将其从树中删除。

注意:我当然更喜欢淡入淡出+折叠动画。

通常你会通过使用来获得一个元素

var tr = document.getElementById("the table row's id");

但表格行没有容易知道的 ID。由于存在多行,因此服务器在构建表时会生成 ID。我意识到一些解决方案将不得不涉及改变:

<TR>

进入

<TR runat="server">

这样每个表行都会有服务器生成的标识,但是我如何从 javsscript 引用生成的名称?

通常我会认为脚本问题可以通过使用多个参数来解决:

function DeleteItem(tableRowElement, deleteUrl)
{
   //Do a web-hit of deleteUrl to delete the item


   //remove tableRowElement DOM object from the document tree
}

但问题只是被推到了别处:如何填充 tableRowElement 和 deleteUrl 以调用 javascript 函数?


这样一个简单的问题:将点击从回发转换为客户端。

所涉及的问题数量变得非常愚蠢。这似乎表明

  • 想法解决方案完全不同
  • 没有解决办法

参考文献

Stackoverflow: How do I fade a row out before postback?

Stackoverflow: Javascript before asp:ButtonField click

asp.net: Accessing repeater elements from javascript.

Stackoverflow: How to access repeater generated elements?

【问题讨论】:

  • 六个小时无处可去,我可以花一个小时编写一个问题
  • 你愿意使用jQuery吗?
  • 取决于它是否免费并且除了将程序集 dll 安装到 bin 文件夹之外不需要任何设置
  • 它是免费的,除了组装ddl之外不需要任何设置。这是一个很好的资源,可以为您以前可能没有想到的一些很酷的功能打开许多大门。
  • 在这个问题得到解决之前我不会看它;否则我只是在玩一些没有实际应用的东西。

标签: asp.net ajax


【解决方案1】:

jQuery可以帮你挖标签:

$("[id$=linkDelete]").click(function() {
    DeleteItem(this.href);
});

该代码表示​​“查找 ID 以 'linkDelete' 结尾的所有 DOM 元素并连接以下点击事件处理程序”。

【讨论】:

  • 你能扩展这个答案吗?这段代码去哪里了,怎么去那里的,“this.href”包含什么?
【解决方案2】:

我建议不要以这种方式通过链接实现删除功能。 Delete links are a security risk.

相反,最好要求在该网址上发布帖子。如果你想做 ajax,我强烈建议你使用 javascript 框架,这样你就不必处理不同浏览器实现 XmlHttpRequests 的差异。

例如,在 jQuery 中你可以这样做:

$.post('Delete.aspx',{itemGuid:'{19a149db-5675-4eee-835d-3d78372ca6f9}'},
    function(data, textStatus) {
        if (textStatus == 'success') {
            $(this).parents('tr:eq(0)').fadeOut();
        }
    });

这将同时进行 ajax 调用和你想要的淡出效果。

然后您可以从 Request.Form["itemGuid"] 访问 Delete.aspx 中的项目 guid,这样就不会受到链接攻击。

防止回发

服务器正在生成回发连线,因为您正在使用服务器控件。使用没有 runat='server' 指令的普通 &lt;a&gt; 标签。

表行标识

我通常通过对某种 ID 列进行数据绑定并将其放入转发器模板中来做到这一点:

<tr id='<%#Eval("ID")%>'>

附:我讨厌听起来像个狂热分子,但 jQuery 将使所有这些事情变得容易一个数量级。如果可以的话,你真的应该考虑一下。否则,如果您试图以一致的方式跨浏览器实现这些功能,您将陷入痛苦的境地。

附言如果仅从 javascript 调用 Delete.aspx 和类似的 url,我建议改用 ashx http 处理程序。您可以执行所有相同的服务器逻辑,而无需完整页面的不必要开销。

【讨论】:

  • 我注意到代码中包含一个 Guid,您能否指出此代码是如何生成的、它的去向以及它是如何到达那里的?
  • 我只是从您的代码中将其作为 id 字段的示例。据我所知,目前无法在 jQuery 中生成 guid。 $.post 的第二个字段是您要发布到服务器的表单变量的名称-值对的集合。
【解决方案3】:

我的通常看起来像

<asp:LinkButton runat="server" OnClientClick='<%# Eval("ID", "DeleteItem(this, \"{0}\"); return false;") %>' Text="Delete" />

这将使html看起来像

<a id="blah_blah_ctl01" onclick='DeleteItem(this, "{19a149db-5675-4eee-835d-3d78372ca6f9}"); return false;'>Delete</a>

我包含“this”引用,以便您可以访问 dom 并删除链接...或者它是父链接或其他链接。从那里使用 jQuery 来实际进行发布和 DOM 操作非常简单。 “返回错误;”禁用回发。

【讨论】:

    【解决方案4】:

    其他回答者发现了与问题的不同方面相关的各种位。我设法拼凑出一个完整的解决方案。我已经在这里复制/粘贴了相关的片段。

    第一个重要的变化是使用 asp:LinkBut​​ton,它允许作为 OnClientClick 事件,让您可以直接访问 javascript OnClick 事件:

    <asp:repeater ID="itemsRepeater"
          OnItemDataBound="itemsRepeater_ItemDataBound"
          runat="Server">
       <itemtemplate>
          <tr>         
             <td>
                <asp:HyperLink ID="linkView" runat="server"
                   Text="<%# GetItemText((Item)Container.DataItem) %>"
                   NavigateUrl="<%# GetViewItemUrl((Item)Container.DataItem) %>" />
             </td>
             <td>
                <asp:LinkButton ID="linkImpregnate" runat="server"
                       Text="Impregnate"
                       OnClientClick="<%# GetImpregnateUrl((Item)Container.DataItem) %>" />
             </td>
          </tr>
       </itemtemplate>
    </asp:repeater>
    

    代码隐藏手动构建包含 javascript 调用的演示代码(分离控制器和视图!)。

    protected string GetNodeAcknowledgementClientClick(Item item)
    {
       if (!(item is HotGirl))
          return ""; //this shouldn't be called for non-acknowledgements, but i won't fail
    
       HotGirl girl = (HotGirl)item;
    
       String szOnClientClick =
             "return ImpregnateGirl(this, "+
                   Toolkit.QuotedStr(girl.GirlGUID.ToString()) + ", "+
                   Toolkit.QuotedStr(GetItemName(item))+");";
    
       return szOnClientClick;
    }
    

    最后在 aspx 中,我找到了一个随机点来混入一些 javascript:

    <script type="text/javascript" src="Javascript/jquery.js"></script>  
    <script type="text/javascript">
       //<![CDATA[
       function DeleteItem(sender, girlGuid, girlName)   
       {
          if (!confirm("Are you sure you want to impregnate "+girlName+"?"))
          {
             return false;
          }
    
          $.post(
             'ImpregnateGirl.aspx?GirlGUID='+nodeGuid,
                   function(data, textStatus) {
                      if (textStatus == 'success') 
                      {
                         $(sender).parents('tr:eq(0)').hide();
                      }
                      else
                      {
                         return false;
                      }
                   }
          );
    
          //return false to suppress the postback
          return false;
       }
    //]]>
    </script>
    

    我会让 jQuery 做一个帖子,作为一个安全措施,就像家伙建议的那样,但是 jQuery 会给出一个错误,而不是发布。与其关心,我选择不关心。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-12
      • 1970-01-01
      • 1970-01-01
      • 2011-05-10
      • 2021-09-09
      • 2010-10-22
      • 2018-10-07
      • 1970-01-01
      相关资源
      最近更新 更多