web-dev-qa-db-fra.com

Référencez-vous le contrôle ASP.NET par ID en JavaScript?

Lorsque les contrôles ASP.NET sont rendus, leurs identifiants changent parfois, comme s'ils se trouvent dans un conteneur de dénomination. Button1 peut en fait avoir un identifiant de ctl00_ContentMain_Button1 lors du rendu, par exemple.

Je sais que vous pouvez écrire votre JavaScript sous forme de chaînes dans votre fichier .cs, obtenir l'ID client du contrôle et injecter le script dans votre page à l'aide de clientscript, mais existe-t-il un moyen de référencer un contrôle directement à partir de JavaScript en utilisant ASP.NET Ajax?

J'ai trouvé que l'écriture d'une fonction pour analyser le dom récursivement et trouver un contrôle qui CONTIENT l'id que je veux n'est pas fiable, donc je cherchais une meilleure pratique plutôt qu'une solution de contournement.

46
NetHawk

Oh, et je l'ai également trouvé, au cas où quelqu'un d'autre aurait ce problème.

Utilisez un sélecteur jQuery personnalisé pour les contrôles asp.net: http://john-sheehan.com/blog/custom-jquery-selector-for-aspnet-webforms/

0
NetHawk

Cet article de Dave Ward pourrait avoir ce que vous cherchez:

http://encosia.com/2007/08/08/robust-aspnet-control-referencing-in-javascript/

Extrait de l'article:

En effet, il y en a. La meilleure solution consiste à utiliser du code ASP.NET en ligne pour injecter la propriété ClientID du contrôle:

$get('<%= TextBox1.ClientID %>')

Désormais, l'ID d'élément client correct est référencé, quelle que soit la structure de la page et le niveau d'imbrication du contrôle. À mon avis, le très faible coût de performance de cette méthode en vaut la peine pour rendre votre script client plus résistant au changement.

Et un exemple de code de Dave à partir du fil de commentaires de ce post:

<script>
  alert('TextBox1 has a value of: ' + $get('<%= TextBox1.ClientID %>').value);
</script>

Le fil de commentaires de l'article que j'ai lié ci-dessus a également une bonne discussion.

70
Chuck

Vous pouvez modifier la propriété ClienIDMode du contrôle en 'Static' qui donnera le même ID que celui que vous donnez au contrôle dans le code .NET.

<asp:TextBox ID="TextBox1" ClientIDMode="Static" runat="server"></asp:TextBox> 

résultera:

<input name="ctl00$MainContent$TextBox1" type="text" id="TextBox1"> 

vous avez donc le même ID.

16
Sudi

Quelques réflexions à ce sujet:

1) J'ai eu beaucoup de chance d'obtenir des éléments par classe css au lieu d'id car les identifiants asp.net ne sont pas fiables comme vous l'avez dit. J'utilise cette fonction et elle fonctionne assez bien:

function getElementsByClass(searchClass,node,tag) {
 var classElements = new Array();
 if ( node == null )
    {
        node = document;
    }

 if ( tag == null )
    {
        tag = '*';
    }

 var els = node.getElementsByTagName(tag);
 var elsLen = els.length;
 var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");

 for (i = 0, j = 0; i < elsLen; i++) 
    {
        if ( pattern.test(els[i].className) ) 
            {
                classElements[j] = els[i];
                j++;
            }
      }
 return classElements;
}

2) jQuery aide ici beaucoup. En utilisant jQuery, vous pouvez obtenir de manière fiable des éléments où l'id se termine par une certaine chaîne. Bien que ce ne soit pas "la" raison d'utiliser jQuery, c'est certainement un plus.

3) Cela sera corrigé dans asp.net 4.0 alors accrochez-vous :-) http://weblogs.asp.net/asptest/archive/2009/01/06/asp-net-4-0- clientid-overview.aspx

12
brendan

Je ne pense pas qu'il existe une seule "meilleure pratique" pour ce faire. Il existe de nombreuses pratiques plutôt bonnes. Voici la nôtre:

Chaque contrôle doté de fonctionnalités côté client affiche un bloc de script en ligne, directement sous le balisage du contrôle:

<span id="something_crazy_long">
    control markup
</span>
<script type="text/javascript">new CustomControl('something_crazy_long');</script>

Chaque contrôle a un JS d'accompagnement comme:

var CustomControl = function(id) {
    this.control = document.getElementByID(id);
    this.init();
};

CustomControl.prototype.init = function() {
    //do stuff to wire up relevant events
};

Dans le codebehind, nous faisons quelque chose comme:

class CustomControl : Control

override void Render(HtmlTextWriter writer)
{
    writer.WriteBeginTag("span");
    writer.WriteAttribute("id", this.ClientID);
    writer.Write(HtmlTextWriter.TagRightChar);
    //write control markup
    writer.WriteEndTag("span");
    writer.WriteBeginTag("script");
    writer.WriteAttribute("type", "text/javascript");
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.Write(
        string.Format("new CustomControl('{0}');", this.ClientID)
    );
    writer.WriteEndTag("script");
}
0
Rex M

Je fais quelque chose de similaire à Rex M, sauf pour éviter plusieurs balises de script.J'utilise une fonction dans ma classe de base de page pour enregistrer les contrôles que je vais utiliser côté client, puis les recracher en html dans 1 balise de script.

Vous pouvez même sous-classer vos contrôles pour vous inscrire automatiquement avec la fonction ou utiliser une propriété booléenne pour définir si vous allez les utiliser côté client.

0
Element

Je préfère les balises liées aux données dans le balisage document.getElementById ('<% # TextBox1.ClientID%>'). Value, plutôt que l'utilisation de l'implémentation de balises côté serveur <% = TextBox1.ClientID%>.

Les balises côté serveur vous interdisent d'ajouter des contrôles au dom dans le code derrière. Ce besoin survient généralement lorsque vous développez votre application et l'approche liée aux données peut vous éviter des réécritures majeures.

Lorsque vous utilisez des balises côté serveur, également appelées "blocs de code", exécutez cette opération courante

this.Form.Controls.Add (myContorl);

génère cette erreur au moment de l'exécution:

La collection Controls ne peut pas être modifiée car le contrôle contient des blocs de code (c'est-à-dire <% ...%>).

Malheureusement, cela ne devient souvent évident par nature qu'après avoir construit votre site Web.

Lors de l'implémentation du contrôle lié aux données '<% # TextBox1.ClientID%>', résolvez la valeur des propriétés de contrôle référencées dans le balisage, à l'endroit approprié tel que la fin de la liaison de données

Page.DataBind ()

Gardez à l'esprit que Page.DataBind () entraîne également les contrôles enfants sur la page DataBind, cela peut être un effet secondaire indésirable si la page gère la liaison de données de certains contrôles enfants séparément. Si tel est le cas, la liaison de données peut être effectuée sur le contrôle individuel comme ceci:

TextBox1.DataBind ()

Une évolution des applications conduit finalement à une sorte de fonctionnalité à l'échelle du site de base où vous voudrez peut-être ajouter des contrôles de base, une fois que vous avez jalonné votre application de site Web avec des balises côté serveur, les remplacer par des liaisons de données devient problématique, en particulier lorsque les pages ont été codées pour gérer la liaison de données par eux-même.

0
David Sopko

Pour 'ctl00_ContentMain_Button1' - Dans asp.net lorsque la page s'affiche dans le navigateur, la première partie reste la même 'ctl00'. La deuxième partie est l'ID de ContentPlaceHolder utilisé "ContentMain". Le troisième est l'ID d'un contrôle 'Button1'

J'ai aimé cela http://codedotnets.blogspot.in/2012/01/how-get-id-server-control-javascript.html

0
suyog