2013-06-14 13 views
7

Pracuję nad większym projektem z AngularJS. Dlatego chcę, aby praca dla jednej formy była tak łatwa, jak to tylko możliwe. Ponieważ jesteśmy również za pomocą bootstrap, kod dla pojedynczego pola wejściowego w formie jest dość rozwlekły, może jakJak mogę automatycznie dodawać etykiety do pól wejściowych?

<div class="control-group"> 
    <label class="control-label" for="inputEmail">Email</label> 
    <div class="controls"> 
    <input type="text" id="inputEmail" placeholder="Email"> 
    </div> 
</div> 

Gdybym mógł napisać jeden tag jak

<custom-input 
    label="Email" 
    name="inputEmail" 
    placeholder="Email" 
    type="text" 
    ... > 
</custom-input> 

zamiast tego będzie pomagają utrzymać kod w czystości, a praca jest prosta.

Aby to osiągnąć, pracuję nad niestandardową dyrektywą AngularJS. Moja dyrektywa używa obecnie szablonu podobnego do powyższego przykładu bootstrapu, automatycznie przypisując etykietę do tagu wejściowego. Ponadto funkcja kompilatora dyrektywy przenosi wszystkie atrybuty ze znacznika wejścia niestandardowego do rzeczywistego znacznika wejściowego, aby ułatwić dostosowanie niestandardowego znacznika wejściowego.

app.directive('customInput', function() { 
    return { 
     require: 'ngModel', 
     restrict: 'E', 
     template: '<div>' + 
        '<label for="{{ name }}">the label</label>' + 
        '<input id="{{ name }}" ng-model="ngModel" />' + 
       '</div>', 
     scope: { 
       ngModel: '=', 
       name: '@name', 
      }, 
     replace: true, 
     compile: function (tElement, tAttrs, transclude) { 
      var tInput = tElement.find('input'); 

      // Move the attributed given to 'custom-input' 
      // to the real input field 
      angular.forEach(tAttrs, function(value, key) { 
       if (key.charAt(0) == '$') 
        return; 
       tInput.attr(key, value); 
       tInput.parent().removeAttr(key); 
      }); 

      return; 
     }, 
    }; 
}); 

na przepełnienie stosu, istnieje wiele pytań dotyczących tworzenia niestandardowych pól wejściowych, ale oni zajmują się data binding, custom formatting lub binding to ng-repeat.

Moje podejście ma jednak inny problem: gdy powiązanie danych działa poprawnie, zintegrowany moduł sprawdzania poprawności formularza Angular jest zdezorientowany, gdy pole wejściowe jest "wymagane". Z jakiegoś powodu sprawdzanie poprawności nie rozpoznaje nowego pola wejściowego i zamiast tego zachowuje nieprawidłowy formularz z powodu jakiegoś martwego odwołania, które ma pustą wartość. Zobacz the minimal example.

Skąd się bierze martwa referencja? Jak mogę zaktualizować referencje modułu sprawdzania poprawności? Czy istnieje lepszy sposób na osiągnięcie mojego ogólnego celu?

Odpowiedz

4
  1. Jako atrybut boolowski istnieje odpowiednia wymagana właściwość, która jest nadal prawdziwa w div, nawet jeśli atrybut został przeniesiony.
  2. Wymagany atrybut nie jest przenoszony, musi być pomijany, ponieważ nie ma żadnej wartości. Nie wiem, jak dodać go do elementu za pomocą javascript bez wartości, ale używając formularza required="required" naprawia, że ​​przy przenoszeniu atrybutów użyje kopii twojego elementu po fazie kompilacji, myślę, że to zachowuje wymaganą właściwość od ustawienia
  3. Musisz z jakiegoś powodu przypisać wyższy priorytet, może z powodu ng-model, który nie jest usuwany z div, ponieważ nazwa w tattrs to ngModel (chociaż usunięcie z elementu div nie powoduje usunięcia potrzeba priorytetu)

http://plnkr.co/edit/5bg8ewYSAr2ka9rH1pfE?p=preview

Ja tylko zmienić żądany atrybut być required="required" i dodać te dwie linie do deklaracji dyrektywy:

transclude: true, 
    priority: 10, 

kładę ng-transclude na etykiecie szablonu przy okazji więc zawartość Twojego elementu pójdzie w etykieta i nie musisz mieć tego atrybutu.

+0

Dziękuję Jason! Użycie 'tInput.prop (key, true)' zamiast 'attr'-call dla atrybutów z' value == '' 'robi lewę, jeśli nie chcesz używać' required = "required" '. –

+0

Chciałbym mieć tę odpowiedź na pytanie kątowe (2+)! – PaulCo

Powiązane problemy