Angular-BookMonkey: Unterschied zwischen den Versionen

Aus Info-Theke
Zur Navigation springen Zur Suche springen
 
(7 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 4: Zeile 4:


= Schritte =
= Schritte =
<source lang="bash">ng new BookMonkey -p bm
<syntaxhighlight lang="bash">ng new BookMonkey -p bm
# ... Angular routing: y
# ... Angular routing: y
# Rest: leere Eingabe
# Rest: leere Eingabe
npm install semantic-ui-css
npm install semantic-ui-css
</source>
</syntaxhighlight>


* Änderung in angular.json:
* Änderung in angular.json:
Zeile 19: Zeile 19:
</pre>
</pre>
* neues Interface
* neues Interface
<source lang="bash">ng g interface shared/book
<syntaxhighlight lang="bash">ng g interface shared/book
ng g component book-list
ng g component book-list
</source>
ng g component book-list-item
</syntaxhighlight>


* Anpassungen in booklist.component.html
* Anpassungen in booklist.component.html
Zeile 29: Zeile 30:
* Dekorator @Component
* Dekorator @Component
* Initialisierung nicht im Konstruktor, sondern in <code>ngOnInit(): void(){}</code>
* Initialisierung nicht im Konstruktor, sondern in <code>ngOnInit(): void(){}</code>
* Alle Bausteine der Anwendung werden mittels <code>@NgModule()</code> in Angular-Modulen organisiert.
* Alle Bausteine der Anwendung werden mittels <code>@NgModule()</code> in Angular-Modulen organisiert. Automatisch mit <code>ng g component...</code> erledigt in app.module.ts.
* Eine Komponte muss immer in declarations eines Moduls registriert werden.
* Eine Komponte muss immer in ''declarations'' eines Moduls registriert werden. Automatisch mit <code>ng g component...</code> erledigt.
* Verschachtelung von Komponenten über (CSS-)Selektor.
=== Selektoren ===
* div.active Div-Element mit CSS-Klasse active
* input[type=text] Eingabefeld vom Typ Text
* li:nth-child(2) jedes zweite Listenelement innerhalb des Elternelements <code><li></code>
* my-element Element mit Tag <code><my-element></code>
* [myAttr] Attribut, z.B.. <code><div myAttr="123"</div></code>
* [myAttr=bar] Attribut, z.B.. <code><div myAttr="bar"</div></code>
* .myClass Elemente mit CSS-Klasse myClass, z.B. <code><div class="myClass"</div></code>
'''Konvention''': möglichst nur Elementnamen verwenden
 
== Property-Bindings ==
* Bringt Daten von der Komponente in Kindelemente im Komponentenbaum.
<pre><my-component [property]="expression"></my-component>
</pre>
* Datenänderung führt automatisch zu Anzeigeaktualisierung
* Auch beliebige Attribute im DOM-Baum sind ansprechbar:
<syntaxhighlight lang="ts">const myImg = document.getElementById('myImg');
myImg.src = 'angular.src';
myImg.style.border = '1px solid black';
</syntaxhighlight>
* HTML-Element ist konstanter Text, Dynamik wird durch Interpolation und die Property-Bindings erzeugt.
* Alternative Schreibweisen:
<pre><!-- Interpolation -->
<element property="{{ expression }}"</element>
<!-- Textkonstante in Ticks einfügen: -->
<element [property]="'value'"></element>
</pre>
=== Beispiele ===
<pre><!-- URL und Title werden aus der Komponente x.myUrl bzw. x.myTitle genommen -->
<img [src]="myUrl" [title]="myTitle" />
<button [disabled]="isDisabled">Do it</button>
<p [textContent]="'DubuDubuDuu'"></p>
<my-component [foo]="1+1"></my-component>
</pre>
=== Weitere Arten von Property-Bindings ===
* Attribute-Bindings: Setzen von Attributwerten <code>[attr.colspan]</code>
<pre><td [attr.colspan]="myColSpan"></td>
<a [attr.role]="myRole>Link</a>
</pre>
* Class-Bindings: Zuweisen von CSS-Klassen: <code>[class.myCssClass]</code>, wenn Bedingung ("expression") true ist.
** Alternative <code>[ngClass]</code>, wenn mehrere gleichzeitig zugewiesen werden sollen.
<pre><element [class.myClass]="hasMyClass"></element>
<div [ngClass]="[ active: isActive, 'has-error': hasError, disabled: isDisabled, myClass: hasMyClass }"></div>
</pre>
* Style-Bindings: Hinzufügen von CSS-Stilen: <code>[style.color]</code>
** Mehrere Zuweisungen mittels <code>[ngStyle]</code>.
<pre><! Achtung, funktioniert nicht, da aus Sicherheitsgründen verboten: -->
<element style="color: {{ myColor }}"></element>
<element [style.color="myColor"></element>
<div [ngStyle]="{ 'color': myColor, 'padding': '10px' }"></div>
<div [ngStyle]="myStyles"></div>
</pre>
== Rückfluss DOM-Property in Komponente ==
* Import von angular/core
* Dekorator @Input() bzw. @Input('domProperty') ('''nicht empfohlen''').
* Bei Fehler "has no initializer and is not definitely assigned in the constructor": undefined zulassen (! nach dem Variablennamen).
<syntaxhighlight lang="ts">import { component, Input } from '@angular/core';
@Component({
  selector: 'my-component';
templateUrl: './my.compoent.html';
})
export class MyComponent {
  @Input() domProperty!: string;
  @Input('domProperty') myProperty: string;
  constructor() { }
}
</syntaxhighlight>
 
== Event-Bindings ==
* Notation: DOM-Event in runde Klammern gesetzt:
<pre><element> (myEvent)="myHandler()"></element>
</pre>
=== Events ===
Die Namen der Angular-Events sind nicht die DOM-Namen, z.B. "click" statt "onClick"
* click: einfacher Mausklick
* change: Ändern eines Werts in Formularfeld
* dblclick: Doppelklick
* keyup: Taste wird losgelassen
* focus: Feld bekommt den Fokus (Maus oder Tastatur)
* blur: Feld verliert den Fokus
* keydown: Taste wird gedrückt
* mouseover: Maus wird auf Element bewegt
* moseout: Maus verlässt Element
* contextmenu: Aufruf des Kontextmenüs
* select: Auswahl von Text
* copy, past: Text kopieren oder einfügen
* submit: Formular wird abgeschickt
 
Beispiel:
<pre><input (keyup)="myKeyHandler($event)" type="text" />
</pre>@Component({...})
export class MyComponent {
myKeyHandler(e: KeyboardEvent) {
  console.log(e);
  }
}
</pre>
=== Events selber definieren ===
* Verwenden des Dekorators @Output
* Auslösung durch <code>emit(value)</code>
* In Hauptkomponente einbinden
<pre><event-component (fooEvent)="handleFoo"
</event-component>
</pre>
 
Beispiel:
<pre><button (click)="handleClick()">foo auslösen</button>
</pre>
<pre>import { Component, EventEmitter, Output } from @angular/core;
@Component({ ... })
export class EventComponent {
  @Output() fooEvent = new EventEmitter<any>;
  handleClick() {
    this.fooEvent.emit();
  }
}
</pre>

Aktuelle Version vom 12. März 2023, 07:39 Uhr

Links[Bearbeiten]

Schritte[Bearbeiten]

ng new BookMonkey -p bm
# ... Angular routing: y
# Rest: leere Eingabe
npm install semantic-ui-css
  • Änderung in angular.json:
    • projects -> BookMonkey -> architect -> build -> options -> styles:
    • projects -> BookMonkey -> architect -> test -> options -> styles:
  "styles": [
    "node_modules/semantic-ui-css/semantic.css"
  ],
  • neues Interface
ng g interface shared/book
ng g component book-list
ng g component book-list-item
  • Anpassungen in booklist.component.html
  • Anpassungen in booklist.component.js
  • Eintrag in app.component.html: <bm-book-list></bm-book-list>

Komponente[Bearbeiten]

  • Dekorator @Component
  • Initialisierung nicht im Konstruktor, sondern in ngOnInit(): void(){}
  • Alle Bausteine der Anwendung werden mittels @NgModule() in Angular-Modulen organisiert. Automatisch mit ng g component... erledigt in app.module.ts.
  • Eine Komponte muss immer in declarations eines Moduls registriert werden. Automatisch mit ng g component... erledigt.
  • Verschachtelung von Komponenten über (CSS-)Selektor.

Selektoren[Bearbeiten]

  • div.active Div-Element mit CSS-Klasse active
  • input[type=text] Eingabefeld vom Typ Text
  • li:nth-child(2) jedes zweite Listenelement innerhalb des Elternelements
  • my-element Element mit Tag <my-element>
  • [myAttr] Attribut, z.B.. <div myAttr="123"
  • [myAttr=bar] Attribut, z.B.. <div myAttr="bar"
  • .myClass Elemente mit CSS-Klasse myClass, z.B. <div class="myClass"

Konvention: möglichst nur Elementnamen verwenden

Property-Bindings[Bearbeiten]

  • Bringt Daten von der Komponente in Kindelemente im Komponentenbaum.
<my-component [property]="expression"></my-component>
  • Datenänderung führt automatisch zu Anzeigeaktualisierung
  • Auch beliebige Attribute im DOM-Baum sind ansprechbar:
const myImg = document.getElementById('myImg');
myImg.src = 'angular.src';
myImg.style.border = '1px solid black';
  • HTML-Element ist konstanter Text, Dynamik wird durch Interpolation und die Property-Bindings erzeugt.
  • Alternative Schreibweisen:
<!-- Interpolation -->
<element property="{{ expression }}"</element>
<!-- Textkonstante in Ticks einfügen: -->
<element [property]="'value'"></element>

Beispiele[Bearbeiten]

<!-- URL und Title werden aus der Komponente x.myUrl bzw. x.myTitle genommen -->
<img [src]="myUrl" [title]="myTitle" />
<button [disabled]="isDisabled">Do it</button>
<p [textContent]="'DubuDubuDuu'"></p>
<my-component [foo]="1+1"></my-component>

Weitere Arten von Property-Bindings[Bearbeiten]

  • Attribute-Bindings: Setzen von Attributwerten [attr.colspan]
<td [attr.colspan]="myColSpan"></td>
<a [attr.role]="myRole>Link</a>
  • Class-Bindings: Zuweisen von CSS-Klassen: [class.myCssClass], wenn Bedingung ("expression") true ist.
    • Alternative [ngClass], wenn mehrere gleichzeitig zugewiesen werden sollen.
<element [class.myClass]="hasMyClass"></element>
<div [ngClass]="[ active: isActive, 'has-error': hasError, disabled: isDisabled, myClass: hasMyClass }"></div>
  • Style-Bindings: Hinzufügen von CSS-Stilen: [style.color]
    • Mehrere Zuweisungen mittels [ngStyle].
<! Achtung, funktioniert nicht, da aus Sicherheitsgründen verboten: -->
<element style="color: {{ myColor }}"></element>
<element [style.color="myColor"></element>
<div [ngStyle]="{ 'color': myColor, 'padding': '10px' }"></div>
<div [ngStyle]="myStyles"></div>

Rückfluss DOM-Property in Komponente[Bearbeiten]

  • Import von angular/core
  • Dekorator @Input() bzw. @Input('domProperty') (nicht empfohlen).
  • Bei Fehler "has no initializer and is not definitely assigned in the constructor": undefined zulassen (! nach dem Variablennamen).
import { component, Input } from '@angular/core';
@Component({
  selector: 'my-component';
templateUrl: './my.compoent.html';
})
export class MyComponent {
  @Input() domProperty!: string;
  @Input('domProperty') myProperty: string;
  constructor() { }
}

Event-Bindings[Bearbeiten]

  • Notation: DOM-Event in runde Klammern gesetzt:
<element> (myEvent)="myHandler()"></element>

Events[Bearbeiten]

Die Namen der Angular-Events sind nicht die DOM-Namen, z.B. "click" statt "onClick"

  • click: einfacher Mausklick
  • change: Ändern eines Werts in Formularfeld
  • dblclick: Doppelklick
  • keyup: Taste wird losgelassen
  • focus: Feld bekommt den Fokus (Maus oder Tastatur)
  • blur: Feld verliert den Fokus
  • keydown: Taste wird gedrückt
  • mouseover: Maus wird auf Element bewegt
  • moseout: Maus verlässt Element
  • contextmenu: Aufruf des Kontextmenüs
  • select: Auswahl von Text
  • copy, past: Text kopieren oder einfügen
  • submit: Formular wird abgeschickt

Beispiel:

<input (keyup)="myKeyHandler($event)" type="text" />

@Component({...})

export class MyComponent {

myKeyHandler(e: KeyboardEvent) {
 console.log(e);
 }

}

Events selber definieren[Bearbeiten]

  • Verwenden des Dekorators @Output
  • Auslösung durch emit(value)
  • In Hauptkomponente einbinden
<event-component (fooEvent)="handleFoo"
</event-component>

Beispiel:

<button (click)="handleClick()">foo auslösen</button>
import { Component, EventEmitter, Output } from @angular/core;
@Component({ ... })
export class EventComponent {
  @Output() fooEvent = new EventEmitter<any>;
  handleClick() {
    this.fooEvent.emit();
  }
}