• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Angular - stosowanie formularzy

Object Storage Arubacloud
+1 głos
170 wizyt
pytanie zadane 19 października 2022 w JavaScript przez Bartek030 Obywatel (1,460 p.)

Cześć,

Chciałem prosić o drobną pomoc w zrozumieniu a przy okazji ocenę sposobu w jaki tworzę formularze w Angularze. Przykład dotyczy zwykłego logowania (login + hasło).

Chcąc uprościć stylizacje i dodawanie kolejnych pól, wydzieliłem cały input do osobnego komponentu. Na początek utworzyłem interfejs, który zawiera wszystkie własności jakie chcę dodać do danego input'a:

export interface InputTemplate {
    id: string,
    label: string,
    name: string,
    placeholder? : string,
    type: string
}

Później w pliku html, po utworzeniu obiektu, binduję te wartości do danego input'a

<input
        type="{{inputElement.type}}"
        name="{{inputElement.name}}"
        id="{{inputElement.id}}"
        placeholder="{{inputElement.placeholder}}"
        [(ngModel)]="inputValue"
/>

Następnie w komponencie z formularzem do logowania dodaję kolejne input'y (na podstawie relacji parent-child) poprzez utworzenie tablicy inputów:

readonly inputs: InputTemplate[] = [{
        id: "login-username",
        label: "Nazwa użytkownika",
        name: "username",
        placeholder: "Podaj nazwę użytkownika",
        type: "text"
    },
    {
        id: "login-password",
        label: "Hasło",
        name: "password",
        placeholder: "Podaj hasło",
        type: "password"
    }];

a następnie za pomocą ngFor generuję kolejne inputy w html:

<form #loginForm="ngForm" (ngSubmit)="loginUser()">
        <app-input
            *ngFor="let input of inputs"
            [inputElement]="input"
            (inputValueEmitter)="onNewInput($event, input)"
        ></app-input>

        <app-user-button [buttonElement]="loginButton"></app-user-button>
</form>

Wartości z kolejnych input'ów przypisuję do odpowiedniego pola obiektu (w komponencie z formularzem) za pomocą EventEmittera. Generalnie ta metoda jest dla mnie całkiem wygodna, ale mam tutaj wątpliwości. Przez wszystkim chodzi o:

#loginForm="ngForm"

Generalnie w różnych poradnikach jest informacja, że jest to ważny element formularza w Angularze, jego obiekt udostępnia różne właściwości formularza jak i wartości z inputów, pod warunkiem ustawienia atrybutu name. Natomiast w moim przykładzie po kliknięciu submit w tym obiekcie nie są przekazywane żadne wartości z inputów także albo gdzieś po drodze popełniłem błąd albo nie mogę w ten sposób przekazywać wartości. Dlatego też zastanawiałem się nad wyrzuceniem ngFor i dodaniu kilku input komponentów bezpośrednio w HTML.

Z drugiej strony zastanawiam się czy ta referencja i atrybuty name są naprawdę potrzebne. Obecnie przy każdym wywołaniu EventEmitter'a aktualizuje swój obiekt, który przetrzymuje wartości z formularza (tutaj nie ma problemu) i ten obiekt mogę później wysłać (po walidacji) na serwer.

Czy moglibyście podpowiedzieć, które podejście będzie lepsze i czy są jakieś inne ważne powody, dla których powinienem użyć referencji #loginForm?

1 odpowiedź

+2 głosów
odpowiedź 19 października 2022 przez Nudzi mi się Gaduła (4,460 p.)
wybrane 19 października 2022 przez Bartek030
 
Najlepsza
Poczytał był raczej o Reactive Forms  https://angular.io/guide/reactive-forms

Twoje rozwiązanie jest bardziej skomplikowane i mało elastyczne. Na przykłaf nie dodasz selecta czy checkboxa. Dojdzie do tego jakaś walidacja i strasznie się całość rozbuduje.
komentarz 19 października 2022 przez Bartek030 Obywatel (1,460 p.)
Hej, dzięki - to wygląda na całkiem proste w użyciu tylko muszę rozbić ngFor przy tworzeniu formularza.

Co do selectbox i checkbox - raczej myślałem o stworzeniu osobnej templatki do nich - głównie ze względu na stylowanie, a walidacje chciałem wykonać w komponencie przed przypisaniem wartości do finalnego obiektu - w template miałem zamiar tylko dodać odpowiednią pole do wyświetlania wiadomości o błędzie.

Natomiast czy jest jakaś konkretna zaleta stosowania angular'owych formularzy? Nawet w swoim przykładzie powyżej byłem w stanie zbudować kompletny obiekt z danymi z formularza (poprzez komunikacje parent-child), który mogę potem użyć do wykonania operacji na serwerze.
komentarz 19 października 2022 przez Nudzi mi się Gaduła (4,460 p.)
komentarz 19 października 2022 przez Bartek030 Obywatel (1,460 p.)
edycja 19 października 2022 przez Bartek030

Dzięki za linki - po ich analizie zrobiłem tak:

  • dodałem nowe pole w interface typu FormControl
  • w parent component, w którym mam formularz, tak jak poprzednio za pomocą ngFor tworzę child componenty, które są pojdunczym inputem, i przesyłam do nich dane
  • w child component dodaje atrybut [formControl] = "nowePole"
  • w parent komponent tworzę obiekt "model" typu FormGroup i przy wywołaniu metody przypisanej do ngSubmit iteruję po wszystkich inputach i dodaje kontrolki do grupy
this.model.addControl(input.name, input.nowePole);

 Efekt jest zgodny z oczekiwaniami - mam dostęp do wartości z pól oraz wszystkich własności formularza. Zmiana ta nie kosztowała wiele czasu, wydzielenie pojedynczego input'u do osobnego komponentu pozwoliło na szybkie wprowadzenie zmiany do wszystkich formularzy, natomiast i tak mam wrażenie, że rzeczywiście jest to mocno przekombinowane smiley

komentarz 19 października 2022 przez Nudzi mi się Gaduła (4,460 p.)

Można się zgubić w trakcie samego czytania smiley.  Nie ma potrzeby mieszać FormControl i ngModel.  Z FormGroup dostaniesz i znienisz bez problemu wartości.

Jakie zastosowanie ma ten for? Dla logowania wydaje się kompletnie nie trafiony.

 

komentarz 19 października 2022 przez Bartek030 Obywatel (1,460 p.)

Tak, nie dopisałem że ngModel wyrzuciłem smiley jak i całą komunikację z Child do Parent - FormControl zrobił to za mnie smiley

Generalnie chodziło mi o to, żeby utworzyć reużywalny input, który już jest odpowiednio ostylowany, i wywoływać go z formularza, czyli w komponencie formularza tworzę tablicę obiektów:

readonly inputs: InputTemplate[] = [{
        formInput: new FormControl(''),
        icon: faUser,
        id: "login-username",
        label: "Nazwa użytkownika",
        name: "username",
        placeholder: "Podaj nazwę użytkownika",
        type: "text"
    },
    {
        formInput: new FormControl(''),
        icon: faLock,
        id: "login-password",
        label: "Hasło",
        name: "password",
        placeholder: "Podaj hasło",
        type: "password"
    }];

A następnie w HTML tego komponentu za pomocą ngFor tworzę kolejne inputy - ngFor po prostu pozwala mi na uniknięcie duplikowania kodu oraz pozwala na przesłanie jednego obiektu z tablicy:

<form (ngSubmit)="loginUser()">
        <app-input
            *ngFor="let input of inputs"
            [inputElement]="input"
        ></app-input>

        <div class="text-end me-3">
            <a class="remember-me-link">Zapomniałeś hasła?</a>
        </div>

        <app-user-button [buttonElement]="loginButton"></app-user-button>
</form>

Jest to o tyle fajne rozwiązanie, że w razie potrzeby drobnej zmiany, nie muszę tego robić w kilku miejscach - wystarczy tylko w wydzielonym komponencie Input, oraz w razie potrzeby dodania kolejnego input'a wystarczy dodać kolejny obiekt do tablicy

Podobne pytania

+1 głos
1 odpowiedź 310 wizyt
0 głosów
1 odpowiedź 111 wizyt
0 głosów
1 odpowiedź 292 wizyt
pytanie zadane 16 grudnia 2019 w PHP przez Piotr Jarema Użytkownik (970 p.)

92,563 zapytań

141,413 odpowiedzi

319,590 komentarzy

61,948 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...