Jak sprawić, by jQuery wybierał elementy z rozszerzeniem. (kropka) w dowodzie tożsamości?

172

Biorąc pod uwagę następujące klasy i metodę akcji kontrolera:

public School
{
  public Int32 ID { get; set; }
  publig String Name { get; set; }
  public Address Address { get; set; }
}

public class Address
{
  public string Street1 { get; set; }
  public string City { get; set; }
  public String ZipCode { get; set; }
  public String State { get; set; }
  public String Country { get; set; }
}

[Authorize(Roles = "SchoolEditor")]
[AcceptVerbs(HttpVerbs.Post)]
public SchoolResponse Edit(Int32 id, FormCollection form)
{
  School school = GetSchoolFromRepository(id);

  UpdateModel(school, form);

  return new SchoolResponse() { School = school };
}

I następujący formularz:

<form method="post">
  School: <%= Html.TextBox("Name") %><br />
  Street: <%= Html.TextBox("Address.Street") %><br />
  City:  <%= Html.TextBox("Address.City") %><br />
  Zip Code: <%= Html.TextBox("Address.ZipCode") %><br />
  Sate: <select id="Address.State"></select><br />
  Country: <select id="Address.Country"></select><br />
</form>

Jestem w stanie zaktualizować zarówno instancję School, jak i członka Address szkoły. To całkiem miłe! Dziękuję zespołowi ASP.NET MVC!

Jak jednak użyć jQuery, aby wybrać listę rozwijaną, aby móc ją wstępnie wypełnić? Zdaję sobie sprawę, że mógłbym zrobić to po stronie serwera, ale na stronie będą inne dynamiczne elementy, które mają wpływ na listę.

Oto, co mam do tej pory i nie działa, ponieważ selektory wydają się nie pasować do identyfikatorów:

$(function() {
  $.getJSON("/Location/GetCountryList", null, function(data) {
    $("#Address.Country").fillSelect(data);
  });
  $("#Address.Country").change(function() {
    $.getJSON("/Location/GetRegionsForCountry", { country: $(this).val() }, function(data) {
      $("#Address.State").fillSelect(data);
    });
  });
});
Doug Wilson
źródło

Odpowiedzi:

293

Z Grup dyskusyjnych Google :

Użyj dwóch odwrotnych ukośników przed każdym znakiem specjalnym.

Ukośnik odwrotny w selektorze jQuery powoduje zmianę znaczenia następnego znaku. Ale potrzebujesz dwóch z nich, ponieważ ukośnik odwrotny jest również znakiem ucieczki dla ciągów JavaScript. Pierwszy ukośnik odwrotny wymyka się drugiemu, dając ci jeden rzeczywisty ukośnik odwrotny w ciągu - który następnie wymyka następny znak dla jQuery.

Więc myślę, że patrzysz

$(function() {
  $.getJSON("/Location/GetCountryList", null, function(data) {
    $("#Address\\.Country").fillSelect(data);
  });
  $("#Address\\.Country").change(function() {
    $.getJSON("/Location/GetRegionsForCountry", { country: $(this).val() }, function(data) {
      $("#Address\\.State").fillSelect(data);
    });
  });
});

Zobacz także Jak wybrać element według identyfikatora, który ma znaki używane w notacji CSS? w FAQ jQuery.

bdukes
źródło
4
Zastanawiam się, jaka jest racjonalizacja, aby wymagać od programisty zrobienia tego, wydaje się, że prosty zestaw heurystyk w jQuery rozwiązałby ten problem, ponieważ nie ma nic złego w identyfikatorach z kropkami ...
Jason Bunting
5
Gdybyś nie musiał uciekać, jak zapytałbyś element z adresem ID i stanem klasy (zakładając, że jeśli znasz identyfikator, nie dodajesz dużo, określając klasę, ale nadal powinien być ważny, myśleć)?
bdukes
12
Z tego powodu w samym CSS musisz także uciec kropkę w identyfikatorze. Wszystko, co robi jQuery, wymaga przestrzegania zasad określonych przez CSS.
bdukes
6
Możesz także wybrać nazwę zamiast identyfikatora. Na przykład $ ('[name = "Address.Country"]')
Funka,
25

Nie możesz użyć selektora identyfikatora jQuery, jeśli identyfikator zawiera spacje. Użyj selektora atrybutu:

$('[id=foo bar]').show();

Jeśli to możliwe, określ również typ elementu:

$('div[id=foo bar]').show();
Elliot Nelson
źródło
Wolę robić to w ten sposób, niż używać znaków ucieczki ... Oczywiście najlepszym obejściem jest nie używanie kropek w id.
GordonB,
Spacje nie są dozwolone w identyfikatorach, nawet w bardziej liberalnej akceptacji znaków HTML5. stackoverflow.com/questions/70579/…
Jay Blanchard,
To prawda, ale to, czy są dozwolone, czy nie, nie ma znaczenia dla biednego gnojka, który utknął w dodawaniu ozdób okiennych do źle napisanej aplikacji internetowej wdrożonej pod koniec lat 90.
Elliot Nelson
4
aby działać, muszą istnieć znaki: `$ (" div [id = '"+ zmienna +"'] ")` lub `$ (" div [id = 'foo bar'] ")`
olga
Jak powiedział @olga, odpowiedź nie jest już legalna. W szczególności zostanie wyświetlony komunikat o błędzie „Niezauważony błąd: błąd składniowy, nierozpoznane wyrażenie: div [id = foo bar]”
James Moore
13

Escape it for Jquery:

function escapeSelector(s){
    return s.replace( /(:|\.|\[|\])/g, "\\$1" );
}

przykład użycia:

e.find('option[value='+escapeSelector(val)+']')

więcej informacji tutaj .


źródło
2
Rozwiązaniem zgodnie z dokumentacją jQuery jest dodanie tylko jednego znaku „\” (ukośnik). alert (escapeSelector ("some.id")); wyświetli się jako jakiś \ .id. Więc myślę, że zastąpienie wyrażenia regularnego powinno być s.replace (/(:|\.||||)/g, "\\\\ $ 1");
Arun
Mam ten sam problem, dlaczego nikt inny tego nie widzi?
TruthOf42
9

Kandydat do wydania ASP.NET MVC, który właśnie został wydany, rozwiązał ten problem, teraz zastępuje kropki podkreśleniami dla atrybutu ID.

<%= Html.TextBox("Person.FirstName") %>

Renderuje do

<input type="text" name="Person.FirstName" id="Person_FirstName" />

Więcej informacji można znaleźć w uwagach do wydania, począwszy od strony 14.

Dale Ragan
źródło
1
Nie widzę, jak to jest „poprawka” - dlaczego ASP.NET MVC miałby zmieniać identyfikator na coś, czego potrzebuje jQuery? Myślę, że problem tkwi w jQuery, a nie przy użyciu. w ID.
Jason Bunting
7
kropka ma specjalne znaczenie w CSS do identyfikowania / łączenia klas, dlatego posiadanie jej w identyfikatorze jest kłopotliwe. „Problem” nie dotyczy jquery.
Funka
4

Jest to udokumentowane w dokumentacji jQuery Selectors :

Użycie dowolnego z meta-znaków (na przykład !"#$%&'()*+,./:;<=>?@[\]^`{|}~) jako dosłowne część nazwy, należy uciec się z dwóch ukośników: \\. Na przykład element z id="foo.bar", może używać selektora $("#foo\\.bar").

W skrócie, prefiks .z \\następująco:

$("#Address\\.Country")

Dlaczego nie .działa w moim ID?

Problem polega na tym, że .ma specjalne znaczenie, następujący po nim ciąg jest interpretowany jako selektor klasy. Więc $('#Address.Country')pasuje <div id="Address" class="Country">.

Jeśli zmienisz znaczenie jako \\., kropka będzie traktowana jak zwykły tekst bez specjalnego znaczenia, pasujący do żądanego identyfikatora <div id="Address.Country">.

Dotyczy to wszystkich znaków, !"#$%&'()*+,./:;<=>?@[\]^`{|}~które w innym przypadku miałyby specjalne znaczenie jako selektor w jQuery. Po prostu dodawaj \\z wyprzedzeniem, aby traktować je jak zwykły tekst.

Dlaczego 2 \\?

Jak zauważono w odpowiedzi bdukes, potrzebujemy 2 \znaków. \spowoduje zmianę znaczenia następującego znaku w JavaScript. Tak więc, gdy JavaScript zinterpretuje ciąg "#Address\.Country", zobaczy \, zinterpretuje to tak, że weźmie następujący znak literalnie i usunie go, gdy łańcuch zostanie przekazany jako argument do $(). Oznacza to, że jQuery nadal będzie widzieć ciąg jako "#Address.Country".

Tutaj \do gry wkracza drugi . Pierwsza z nich mówi JavaScriptowi, aby zinterpretował drugą jako znak dosłowny (nie specjalny). Oznacza to, że drugi będzie widoczny dla jQuery i zrozumie, że następny . znak jest znakiem dosłownym.

Uff! Może możemy to sobie wyobrazić.

//    Javascript, the following \ is not special.
//         | 
//         |
//         v    
$("#Address\\.Country");
//          ^ 
//          |
//          |
//      jQuery, the following . is not special.
Jon Surrell
źródło
2

Używając dwóch odwrotnych ukośników jest w porządku, działa. Ale jeśli używasz nazwy dynamicznej, mam na myśli nazwę zmiennej, będziesz musiał zastąpić znaki.

Jeśli nie chcesz zmieniać nazw zmiennych, możesz to zrobić:

var variable="namewith.andother";    
var jqueryObj = $(document.getElementById(variable));

i niż masz swój obiekt jquery.

Daniel
źródło
0

Tylko dodatkowe informacje: sprawdź ten problem dotyczący ASP.NET MVC nr 2403 .

Dopóki problem nie zostanie rozwiązany, używam własnych metod rozszerzających, takich jak Html.TextBoxFixed itp., Które po prostu zastępują kropki podkreśleniami w atrybucie id (nie w atrybucie nazwy), więc używam jquery, takiego jak $ ("# Address_Street") ale na serwerze jest to jak Address.Street.

Przykładowy kod jest następujący:

public static string TextBoxFixed(this HtmlHelper html, string name, string value)
{
    return html.TextBox(name, value, GetIdAttributeObject(name));
}

public static string TextBoxFixed(this HtmlHelper html, string name, string value, object htmlAttributes)
{
    return html.TextBox(name, value, GetIdAttributeObject(name, htmlAttributes));
}

private static IDictionary<string, object> GetIdAttributeObject(string name)
{
    Dictionary<string, object> list = new Dictionary<string, object>(1);
    list["id"] = name.Replace('.', '_');
    return list;
}

private static IDictionary<string, object> GetIdAttributeObject(string name, object baseObject)
{
    Dictionary<string, object> list = new Dictionary<string, object>();
    list.LoadFrom(baseObject);
    list["id"] = name.Replace('.', '_');
    return list;
}
gius
źródło
1
z powyższego problemu: „UpdateModel () używa kropki, ponieważ w ten sposób pojawiają się elementy formularza. Elementy formularza używają kropki, ponieważ tak są określone w wywołaniach pomocnika HTML. Wywołania pomocnicze HTML używają kropki, ponieważ tak ViewData.Eval () działa. Wreszcie, ViewData.Eval () używa kropki, ponieważ w ten sposób oddziela się obiekt i jego właściwość w głównych językach .NET Framework. Użycie separatora innego niż kropka w dowolnym punkcie tego łańcucha spowodowałoby przerwanie przepływ dla całego łańcucha ”.
Simon_Weaver,
0

Rozwiązałem problem za pomocą rozwiązania podanego przez jquery docs

Moja funkcja:

//funcion to replace special chars in ID of  HTML tag

function jq(myid){


//return "#" + myid.replace( /(:|\.|\[|\]|,)/g, "\\$1" );
return myid.replace( /(:|\.|\[|\]|,)/g, "\\$1" );


}

Uwaga: usuwam znak „#”, ponieważ w swoim kodzie łączę identyfikator z innym tekstem

Czcionka: Jquery Docs wybiera element ze specjalnymi znakami

Gabriel Molina
źródło