AngularTool: Formelsammlung effektiv ausbauen und Eingaben kontrollieren

Moin Moin,

für eine Formelsammlung sollen einige Bedingungen erfüllt werden.

A) Die Eingabe soll auf Zahlen beschränkt werden
B) Komma-Eingaben sollen in EINEM Punkt geändert werden.
C) Die Werteingabe soll ohne „Enter“ erfolgen
D) Das Ergebnis soll simultan bei jeder Nummer-Eingabe angezeigt werden
E) Die Eingabe soll auf allen Formel-Variablen möglich sein (AxB = C ↔ C/B=A)
F) Viele kleine HTML / Componenten sollen jeweils nur eine Eingabe/Ausgabe steuern G) Die „eigentliche Formel soll im Service hinterlegt werden

Auf der Webseite angulartool.de kann das Ergebnis angeschaut werden. Das ist aber noch sehr verbesserungswürdig und ich bin gespannt auf Eure Kritik.

Leider kann ich den desamten Code nicht im Forum hochladen. Daher meine „Gedanken“ im Einzelen:

A) Hier kommt eine Directive zum Zuge; wobei mit switch / case die zugelassen Zeichen ersichtlich sind.

###  input-restriction.directive.ts

import {Directive, ElementRef, HostListener} from '@angular/core';

@Directive({
  selector: '[appInputRestriction]'
})
export class InputRestrictionDirective {

  constructor(private element: ElementRef) {
  }

  @HostListener('keydown', ['$event'])
  onKeyDown(event: KeyboardEvent) {

    switch (event.key) {
      case '0':        break;
      case '1':        break;
      case '2':        break;
      case '3':        break;
      case '4':        break;
      case '5':        break;
      case '6':        break;
      case '7':        break;
      case '8':        break;
      case '9':        break;
      case ',':        break;
      case '.':        break;
      case 'Backspace':        break;
      case 'Insert':        break;
      case 'ArrowLeft':        break;
      case 'ArrowRight':        break;

      default:        event.preventDefault();
    }
  }
}

Das ensprechende HTML Template sieht so aus:

### kreis-berechnung.component.html

<p>kreis-berechnung works!</p>

<label> Kreis Durchmesser
   <input class="Input"
         [(ngModel)]='D'
         (keyup)="KreisFlaeche(D)"
         appInputRestriction>
</label>
<label> Kreis Fläche
  <input class="Input"
         [(ngModel)]='A'
         (keyup)="KreisDurchmesser(A)"
         appInputRestriction>
</label>

Hier wird über z.B (keyup)="KreisFlaeche(D)" die richtige Formel beim loslassen der Taste aufgerufen. Das Angular Feature [(ngModel)]='D' bindet die Variable D an das Input.value. Die Directive appInputRestriction sorgt für die stressfreie Eingabe von ausschließe der zugelassenen Tasten.

In der #### kreis-berechnung.component.ts wird die Logik der Anzeige verpackt:

import { Component, OnInit } from '@angular/core';
import { KreisFormelService } from '../../_services/kreis-formel.service';

@Component({
  selector: 'app-kreis-berechnung',
  templateUrl: './kreis-berechnung.component.html',
  styleUrls: ['./kreis-berechnung.component.css']
})
export class KreisBerechnungComponent implements OnInit {

  public D: number;
  public A: number;

  constructor(private Kreis: KreisFormelService) {
  }

  ngOnInit() { }

  KreisFlaeche(D) {this.A = this.Kreis.getKreisFlaeche(D.replace(/,/, '.')) };
  KreisDurchmesser(A) {this.D = this.Kreis.getKreisDurchmesser(A.replace(/,/, '.')) };
}

--- und die Formelen von/im dem Service aufgerufen. Hier wird auch über die D.replace(/,/, '.') das Komma zum Punkt gewandelt.

--- Schlussendlich wird im Angular Service die Formelsammlung bereitgestellt.

### kreis-formel.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class KreisFormelService {

  constructor() { };

  getKreisFlaeche (D) {
    return D * D * Math.PI /4 ;
  }

  getKreisDurchmesser (A) {
    return Math.pow(  (A * 4 /Math.PI), 0.5);
  }


}

Ich bin mir sicher, das Ganze Formel und HTML Gedöns kann noch etwas vereinfacht werden. Jedoch möchte ich z.B die im HTML Template eingegeben Varialbe D (Durchmesser) auch in anderen Formeln / HTML Templates GLEICHZEIGIG NUTZEN, um Andere Berechnungen mit dem Durchmesser vorzunehmen (Widerstandsmoment…. )

Grüße Jürgen

  1. Tach!

    A) Hier kommt eine Directive zum Zuge; wobei mit switch / case die zugelassen Zeichen ersichtlich sind.

    Erstell lieber ein Array mit den zulässigen Tasten und prüf mit der Methode includes(), ob die Taste nicht darin enthalten ist, um daraufhin das event.preventDefault() aufzurufen. Das switch-Konstrukt ist sehr umständlich.

    dedlfix.

    1. Naja, die switch Anweisung ist ein Mammut aus der VB Zeit.

      Macht es eigentlich Sinn, sich ein Template im (Gemeinsamen-) Service für jede Formel zu bauen, wobei einerseits die Formelgleichung UND der HTML Code (Min. beiden Input Felder und das "Layout") zu hinterlegen. Wobei der HTML Teil dann ebenfalls an das übergeordnete Modul / Constructor / HTML übergeben wird?

      Dann könnte doch über die Navigation der gewünschte Eingabe/Formelbereich angezeigt werden?

      Grüße Juergen

      1. Tach!

        Macht es eigentlich Sinn, sich ein Template im (Gemeinsamen-) Service für jede Formel zu bauen, wobei einerseits die Formelgleichung UND der HTML Code (Min. beiden Input Felder und das "Layout") zu hinterlegen.

        Nein, Services sind nicht für die Darstellung zuständig. Du kannst aber jeweils eine eigenen Komponente für lediglich die Ausgabe der Formel erstellen. Vor allem dann, wenn diese Ausgabe mehrfach verwendet werden soll oder um die Komplexität der jetzigen Komponente, bestehend aus Ein- und Ausgabe, zu verringern.

        Wobei der HTML Teil dann ebenfalls an das übergeordnete Modul / Constructor / HTML übergeben wird?

        Wenn ein Service HTML-Code liefern soll, muss das als String erfolgen. Damit verlierst du je nach IDE Hilfestellungen bei der Bearbeitung. Um in einer Komponente einen String als HTML-Code auszugeben, sind weitere Kopfstände nötig, damit Angular das Escaping unterlässt. Sowas ist keine gute Idee. Component mit Parameter(n) ist der vorgesehene Weg. Zum organisierenden Zusammenfassen kann man zusammengehörende Teile in ein Modul packen.

        Dann könnte doch über die Navigation der gewünschte Eingabe/Formelbereich angezeigt werden?

        Mehrere Router-Outlets über das Routing zu befüllen ist ein Weg, wenn die Komponenten eigenständig sind und nicht direkt miteinander kommunizieren müssen. Ansonsten würde wohl die Eingabekomponente in ihrem Template die Ausgabekomponente einbinden, dann kann sie die Werte direkt am Parameter der Ausgabekomponente binden. Die Ausgabekomponente kann in der ngOnChanges()-Methode auf Änderungen der Parameter reagieren.

        dedlfix.

        1. Nein, Services sind nicht für die Darstellung zuständig. Du kannst aber Zum organisierenden Zusammenfassen kann man zusammengehörende Teile in ein Modul packen

          Die xxx.module.ts habe ich noch nicht ganz auf meinem "Schirm".

          Ansonsten würde wohl die Eingabekomponente in ihrem Template die Ausgabekomponente einbinden, dann kann sie die Werte direkt am Parameter der Ausgabekomponente binden.

          So wie es es jetzt auch gemacht habe?

          Die Ausgabekomponente kann in der ngOnChanges()-Methode auf Änderungen der Parameter reagieren.

          ngOnChanges() funktioniert nicht, da ich ja "von beiden Seiten" über die umgestellen Formeln zu den Ergebissen kommen. Das könnte aufgrund der Rundungstoleranzen zueiner Endlosschleife führen. Daher der "Trick" mit dem gestaffelten (KeyDown) und (KeyUp) und der hilftreichen Directive!

          -- Auf der Webseite angulartool.de habe ich den Aufbau einmal eingestellt. Da ich nicht den ng build im --prod Mode erstellt habe, kann über den DEBUGGER (FireFox) der Gesamtaufbau gesehen werden. Der Aufbau der Seite dauert je nach Internetverbing "etwas" länger.

          1. Tach!

            Ansonsten würde wohl die Eingabekomponente in ihrem Template die Ausgabekomponente einbinden, dann kann sie die Werte direkt am Parameter der Ausgabekomponente binden.

            So wie es es jetzt auch gemacht habe?

            Ah... da du quasi vorwärts und rückwärts rechnest, ist die Ausgabe des einen die Eingabe des anderen Wertes und umgekehrt. Da ergibt eine separate Ausgabekomponente nicht so sehr einen Sinn. Da hab ich jetzt auch keine bessere Idee.

            -- Auf der Webseite angulartool.de habe ich den Aufbau einmal eingestellt. Da ich nicht den ng build im --prod Mode erstellt habe, kann über den DEBUGGER (FireFox) der Gesamtaufbau gesehen werden. Der Aufbau der Seite dauert je nach Internetverbing "etwas" länger.

            Steht in deinen HTML-Template-Dateien wirklich export default "HTML als String" oder hat das Angular bzw. angular-cli so verzapft?

            dedlfix.

            1. Moin Moin,

              Steht in deinen HTML-Template-Dateien wirklich export default "HTML als String" oder hat das Angular bzw. angular-cli so verzapft?

              Nicht wirklich, dass muss durch Angular oder evtl durch PHPStorm über ein Zusatz hineingekommen sein. Allerdings habe ich irgendwo schon das sehen: export default "HTML als String" um eben HTML Code ins HTML zu implementieren...

              export default "\n <span>Welcome </span>\n <span>{{ title }} app is running!</span>\n\n <app-kreis-berechnung></app-kreis-berechnung>\n\n<router-outlet></router-outlet>\n"

              Das steht im WEBPACK - Verzeichnis und ist def. von Angular. Wie und was immer Angular damit macht, bzw. ob das gut ist für den Brouser, kann ich auch nicht sagen.

              Jedenfalls wird aus einem kleinen Code schon ein dicker Codeschinken... .

              Un das hatte mich ja auf die Idee gebracht, gezielt den Code vom "Formeltemplate" in die Anwendung schreiben. Jedenfalls habe ich im C# das Layout oft per Code (Eingebefelder, Buttons, ect. die genauen Positionen der Elemente) erstellt, damit ich dann Array nutzen konnte. Denn diese Eingabe/Ausgabetechnik benutze ich sehr gerne.

              1. Tach!

                Steht in deinen HTML-Template-Dateien wirklich export default "HTML als String" oder hat das Angular bzw. angular-cli so verzapft?

                Nicht wirklich, dass muss durch Angular oder evtl durch PHPStorm über ein Zusatz hineingekommen sein.

                Tatsächlich, das macht wohl der ng serve kaputt. Der PhpStorm ist es garantiert nicht, der konvertiert an den Dateien nichts. Jedenfalls machts das bei mir auch, was aber nicht weiter auffällt, weil zum Debuggen immer nur die ts-Dateien interessieren.

                dedlfix.

                1. Moin Moin,

                  leider habe ich den Ursprungscode nicht gespeichert. Diesen habe ich aber mit ng build umgesetzt und nicht mit ng build -prod. Dadurch werden weitere "Hilfsteile" mit zu Brouser gebene, wass ja anscheined nicht nur eine Länger Ladezeit im Iternet bedeutet.

                  Ich werde daS mal am WE da etwas genauer betrachten.

                  Denn wenn durch diese Einstellung HTML Code "geschickt" implementiert werden kann, könnte es eine Lösung zu meinen Ansatz sein.

                  1. Tach!

                    leider habe ich den Ursprungscode nicht gespeichert. Diesen habe ich aber mit ng build umgesetzt und nicht mit ng build -prod.

                    Mit Ursprungscode meinst du jetzt nicht deine Quelltexte, oder?

                    Dadurch werden weitere "Hilfsteile" mit zu Brouser gebene, wass ja anscheined nicht nur eine Länger Ladezeit im Iternet bedeutet.

                    Ein build ohne --prod erzeugt Dateien, die für das Debugging geeignet sind, zuzüglich Hilfsdateien, wie .map. Beim Erzeugen eines Produktiv-Builds finden auch noch weitergehende Prüfungen statt. Wenn beispielsweise eine Eigenschaft einer Komponente als private gekennzeichnet ist, sie aber im Template angesprochen wird, geht das problemlos bei einem ng build durch, wird aber bei einem ng build --prod als Fehler gewertet.

                    dedlfix.

                    1. Mit Ursprungscode meinst du jetzt nicht deine Quelltexte, oder?

                      Ja, den Quellcode, welcher einerseits durch Angular-CLI erstellt wird und dann entsprechend modifiziert wird.

                      Leider weiß ich nicht, wie der Quellcode hier im Forum zur Verfügung gestellt werden kann. So habe ich versucht diesen durch die Erstellung des "build" ohne prod halt "sichtbar" zu machen.

                      Im Moment bin ich dabei über Shared Module, Observeables und einer Struktur im Programmaufbau etwas hinzubekommen. Das wird aber noch etwas dauern, denn wie gesagt, ich bin im Angular/JavaScript ein Newby.

                      Auch versuche ich über PHP etwas "beizumischen", ob das eine gute Idee ist, kann ich noch nicht sagen.

                      Auch werde ich vom Routing INNERHALB eines Anwendungsthemas. Z.B alle Biegebalken und es über *ngIf und <div> im HTML steuern.

                      1. Hallo,

                        Leider weiß ich nicht, wie der Quellcode hier im Forum zur Verfügung gestellt werden kann.

                        versuch mal die Taste </> über dem Eingabefenster für Postings.

                        Gruß
                        Jürgen

                        1. Moin Moin,

                          hierbei kann ich ja nur den Text als Quelltext markieren. Bei Angular sind aber ganze Verzeichnisstrukturen gegeben. Diese werden normalerweise als ZIP gespeichert und verschickt. Dass alles im Text darzustellen ist sehr umständlich und zwingt einen alles genau in der/als Anwendung nachzubauen. Angular ist eigentlich ein Framework für JS und Typescript und speziellen "Möglichkeiten". Ähnlich ist es ja auch mit z.B WordPress, da muss ja auch alles zur Verfügung stehen.

                      2. Tach!

                        Leider weiß ich nicht, wie der Quellcode hier im Forum zur Verfügung gestellt werden kann. So habe ich versucht diesen durch die Erstellung des "build" ohne prod halt "sichtbar" zu machen.

                        Ist nicht tragisch, das ist jedenfalls schon ein guter Weg. Ansonsten bietet es sich noch an, ein Stackblitz-Projekt zu erstellen, da kann man alle Quelldateien hinterlegen und es auch laufen lassen. Dafür ist es aber eher sinnvoll, sich auf ein Minimalbeispiel zu beschränken.

                        Im Moment bin ich dabei über Shared Module, Observeables und einer Struktur im Programmaufbau etwas hinzubekommen. Das wird aber noch etwas dauern, denn wie gesagt, ich bin im Angular/JavaScript ein Newby.

                        Auch versuche ich über PHP etwas "beizumischen", ob das eine gute Idee ist, kann ich noch nicht sagen.

                        Eher nicht, aber PHP-Scripte können auf dem Server für den Datenzugriff sorgen (mit HttpClient in Angular als Gegenstück).

                        Auch werde ich vom Routing INNERHALB eines Anwendungsthemas. Z.B alle Biegebalken und es über *ngIf und <div> im HTML steuern.

                        Eine verschachtelte Routingstruktur ist jedenfalls möglich, um eine Hierarchy reinzubringen. Aber ja, wenn innerhalb eine Themas zwischen verschiedenen Aspekten umgeschaltet werden kann, dann ist auch ein solcher Umschalter ok.

                        dedlfix.

                        1. Moin Moin,

                          das "Beispiel" nun im angulartool.de ist komplett mit routing (inkl. child rooting) erstellt worden. Wie zu sehen ist, in der NAV Componente (die blauen Knöpfe) wird es sehr sehr Umständlich - auch die Varialblenübergabe trotz des (nicht vorhandenen) Servises wird auch nicht einfacher. Daher nehme ich Deinen Tipp gerne an, stukturiert -aber so flach wie möglich. Das Ganze dann "gewürzt" mit Interfaces für die Objekte... Wir werden sehen, wohin das Ganze läuft.

                          Grüße Juergen

                          1. Moin Moin,

                            bevor mich die JavaScript Puristen killen, ich komme aus der C# Ecke und setzte auf Angular auf.

                            Mittlerweile habe ich begriffen und halte es für SUPER GUT, dass JS Funktionen Fist-Class-Objekte sind.

                            Aber mit der Implementierung von Berechnungsformel habe ich so meine Probleme.

                            Beispiel:

                            Ich habe 2 Services in Angular

                            Service 1) variable-template.service.ts (Funktioniert so wie ich will)

                            import {Injectable} from '@angular/core';
                            
                            @Injectable({
                              providedIn: 'root'
                            })
                            export class VariableTemplateService {
                            
                            get unit(): string { return this._unit;}
                            set unit(value: string) { this._unit = value;}
                            
                            get scale(): number { return this._scale;}
                            set scale(value: number) { this._scale = value;}
                            
                            constructor(
                                unit: string = null,
                                scale: number = 1,
                            ) {
                                this._scale = scale;
                                this._unit = unit;
                              }
                            }
                            

                            Service 2) unit-converter.service.ts (Sollen eigentlich Logic-Funktionen sein)

                            import {Injectable} from '@angular/core';
                            
                            @Injectable({
                              providedIn: 'root'
                            })
                            export class UnitConverterService {
                            
                              public mmUnit = 1;
                            
                            public unit_mm(unit: string,
                                           scale: number = 1): any {
                            
                              switch (unit) {
                                case 'mm':
                                  return {
                                    unit: 'cm',
                                    scale: this.cmUnit
                                  };
                            
                                case 'cm':
                                  return {unit: 'dm',scale: this.dmUnit,};
                            
                               case 'dm':
                                  return {unit: 'm', scale: this.mUnit,};
                            
                                case 'm':
                                  return {unit: 'mm', scale: this.mmUnit,};
                            
                                default:
                                  return {unit: 'mm',scale: 1,};
                              }
                            }
                            
                            constructor() {
                            }  // LEER und kann deshalb keine neue Instanz über ... =new… erstellen
                            

                            HIER IST MEINE FAGE: WIE KANN ICH DIE FUNKTIONEN (LOGIK UND MATHEFORMELEN SINNVOLL ERSTELLEN?

                            Die beiden Services baue ich in einer traeger-Tragarm.component.ts ein. Die Templatevariablen (Object Eigenschaften) können „einfach üver den Aufruf new gebildet werden, Die Funtionen aber eben nicht und nur uber einen weitweren Funktionsaufrug (hier ngInit)

                            import {Component, OnInit} from '@angular/core';
                            import {VariableTemplateService} from '../../../globales/sevices/SI_Values/variable-template.service';
                            import {UnitConverterService} from '../../../globales/sevices/SI_Values/unit-converter.service';
                            
                            
                            @Component({
                              selector: 'jg-traeger-tragarm',
                              templateUrl: './traeger-tragarm.component.html',
                              styleUrls: ['./traeger-tragarm.component.sass']
                            })
                            
                            export class TraegerTragarmComponent implements OnInit {
                            
                            // UND IM CONSTRUCTER MEINE TEMPALTE VARIABLEN BAUE. OK
                              constructor(private _UnitConverterService: UnitConverterService,
                              ) {
                              }
                            
                              public F = new VariableTemplateService('N', 1); // HIER DER AUFRUF ÜBER >NEW
                              public L = new VariableTemplateService('mm', 1);
                            
                            // Hier die Funktionsbildung über den weiteren Funktionsaufruf und daher >im constructor private _UnitConverterService: UnitConverterService,
                            
                            ngOnInit() {
                                  const unit_mm = this._UnitConverterService.unit_mm;
                                }
                            

                            Hier frage ich mich, wie kann ich eine Variable (Objekteigenschft) aus der (Template) componente in die Funktion - kommend aus dem Service- übergeben, dort berechenen werden? Dann soll wiederum das Ergebnis wieder an die (Tempate) Componente (wohl über RETURN) übergeben werden. Ich habe nur Service Beispiele gesehen, wo der Service eine STATISCHES Object (JSON oder DB) hat, dass dann an die aufrufende Componente per RETURN übergeben wird.

                            1. Hallo AngularTool,

                              Für die Auszeichnung von Code gibt es ein Icon oberhalb des Textfeldes und zur Not den Hilfebutton.

                              Bis demnächst
                              Matthias

                              --
                              Du kannst das Projekt SELFHTML unterstützen,
                              indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
                            2. Tach!

                              Hier frage ich mich, wie kann ich eine Variable (Objekteigenschft) aus der (Template) componente in die Funktion - kommend aus dem Service- übergeben, dort berechenen werden?

                              Ich hoffe, ich kann mir einigermaßen zusammenreimen, was du zu erreichen versuchst. Dazu kann ich nur sagen: mach das lieber nicht. Zur Laufzeit einen Service zusammenstellen, indem du Funktionen an Variablen bindest, bringt keine Vorteile gegenüber der bei Angular vorhandenen Dependency Injection. Bau lieber einen Service für die Formeln, oder mehrere Services mit je einer Formel und lass dir die benötigten per DI reinreichen. Wenn du doch lieber eine Factory haben möchtest, dann injizier die Services in diesen Factory-Service und gibt über eine Methode den zu wählenden Service zurück.

                              dedlfix.

                              1. Moin Moin,

                                ich bin mir nicht sicher, ob ich so nun auf dem richtigen (schnellen) weg bin.

                                Das HTML Template in home-page.component.html

                                Das ist die {{was}} <br>
                                
                                A.Eigenschaft2Num -- A = {{A.ValueEigenschaft}} <br>
                                B.Eigenschaft2Num -- B = {{B.ValueEigenschaft}} <br>
                                
                                <button (click)="( moment(A.ValueEigenschaft, B.ValueEigenschaft) )" >A x B </button><br>
                                Erg.: {{Mt.ValueEigenschaft}}   (stimmt erst nach Button Click) <br>
                                <br>
                                
                                Mt: {{Mt}}<br>
                                Mt.NamenEigenschaft: {{Mt.NamenEigenschaft}}<br>
                                Mt.ValueEigenschaft: {{Mt.ValueEigenschaft}}<br>
                                <br>
                                <br>
                                NeuEigenschaft: {{NeuEigenschaft}}<br>
                                NeuEigenschaft.Eigenschaft1: {{NeuEigenschaft.NamenEigenschaft}}<br>
                                NeuEigenschaft.Eigenschaft2Num: {{NeuEigenschaft.ValueEigenschaft}}<br>
                                
                                
                                
                                ---
                                Dann die dazugehörige Compoente. home.page.component.ts
                                
                                ~~~ javascript
                                import { Component, OnInit } from '@angular/core';
                                import { FunctionsObjectService } from '../../Services/functions-object.service';
                                import { VariablenObjectService } from '../../Services/variablen-object.service';
                                
                                @Component({
                                  selector: 'app-home-page',
                                  templateUrl: './home-page.component.html',
                                  styleUrls: ['./home-page.component.css']
                                })
                                export class HomePageComponent implements OnInit {
                                was = 'HomePage';
                                
                                A = new VariablenObjectService('A', 5);
                                B = new VariablenObjectService('B', 2);
                                Mt = new VariablenObjectService('Mt', 0);
                                Func: FunctionsObjectService;
                                
                                // So etwas würde ich gerne für die Funktionen verwenden
                                NeuEigenschaft = new VariablenObjectService('Neues', 4711);
                                
                                  /* constructor() {} // Gehjt nicht, da Service im Constructor angemeldet werden muss*/
                                
                                   constructor(Func: FunctionsObjectService) {
                                     this.Func = Func;
                                   }
                                
                                  ngOnInit() {}
                                
                                  // Ganz übel, da hier die Funktion erstellt wird, und nicht aus dem Service
                                  // moment(a: number , b: number ) { this.Mt = (a * b); }
                                
                                  moment(a: number , b: number ) { this.Mt.ValueEigenschaft = this.Func.Mt(a, b); }
                                
                                  // Mein Ziel etwas einfacher
                                  // moment(a: number , b: number ) { this.Mt = Funktion vom Service} ohne den 2.Aufruf der a, b in this.Func.Mt(a, b)
                                }
                                
                                

                                Hier nun der Service für die Funktionen als function-object.service.ts

                                import { Injectable } from '@angular/core';
                                
                                @Injectable({
                                  providedIn: 'root'
                                })
                                export class FunctionsObjectService {
                                
                                  constructor() {}
                                
                                  Mt(x: number , y: number): number {
                                    return x * y;
                                  }
                                
                                  Diff(x: number , y: number): number  {
                                    return x / y;
                                  }
                                
                                 }
                                
                                
                                Und hier die Variablen (Klasse) als Serive: variablen-object.service.ts
                                
                                ~~~ javascript
                                import { Injectable } from '@angular/core';
                                
                                @Injectable({
                                  providedIn: 'root'
                                })
                                export class VariablenObjectService {
                                
                                  public NamenEigenschaft = 'Unbekannter Variablen Name';
                                  public ValueEigenschaft = 0;
                                
                                  constructor(VariablenNamen: string, Wert: number) {
                                    this.NamenEigenschaft = VariablenNamen;
                                    this. ValueEigenschaft = Wert;
                                
                                    function VarNamen() {
                                      return this.NamenEigenschaft;
                                    }
                                
                                    function VarWert() {
                                      return this.ValueEigenschaft;
                                    }
                                  }
                                }
                                
                                
                                Das läuft soweit, jedoch glaube ich nicht an der Sinnhaftigkeit.
                                Aber das ist doch iergenwo schon DI, oder?
                                
                                Grüße
                                Juergen
                                
                                1. Ich stelle das einaml in die Angulartool.de ein

                                2. Moin Moin,

                                  ich will das Forum nicht vollblubbern, aber es geht natürlich noch besser:

                                  Mit einem logikfreiem HTLM, wo nur der Aufruf erfolgt:

                                  button (click)="( momentMt() )" >A x B </button><br>

                                  Dann in der Componente den Service einladen, und über den constructor und einer Eigenschaft bekanntgeben.

                                  Func: FunctionsObjectService;
                                  
                                     constructor(Func: FunctionsObjectService) {
                                       this.Func = Func;
                                     }
                                  

                                  Und dann die Funktion mit den richtigen Parametern nutzen:

                                   momentMt(){ this.Mt.ValueEigenschaft = this.Func.Mt(this.B.ValueEigenschaft ,
                                  this.A.ValueEigenschaft); }
                                  

                                  Damit kann ich alle Eigenschaften des Templates/Componente sinnvoll einsetzen und meiner saubren Funktion übergeben.

                                  
                                  @Injectable({
                                    providedIn: 'root'
                                  })
                                  export class FunctionsObjectService {
                                  
                                    constructor() {}
                                  
                                    Mt(x: number , y: number): number {
                                      return x * y;
                                    }
                                  
                                    Diff(x: number , y: number): number  {
                                      return x / y;
                                    }
                                  
                                   }
                                  
                                  
                                  1. Hallo AngularTool,

                                    ich will das Forum nicht vollblubbern, aber es geht natürlich noch besser:

                                    Ich möchte dir wirklich ans Herz legen, die Vorschaufunktion zu verwenden, damit deine Beiträge auch entsprechend deiner Absichten formatiert sind.

                                    Bis demnächst
                                    Matthias

                                    --
                                    Du kannst das Projekt SELFHTML unterstützen,
                                    indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
                                  2. Tach!

                                    Dann in der Componente den Service einladen, und über den constructor und einer Eigenschaft bekanntgeben.

                                    Func: FunctionsObjectService;
                                    
                                       constructor(Func: FunctionsObjectService) {
                                         this.Func = Func;
                                       }
                                    

                                    Das geht einfacher, einfach private davorschreiben und schon ist es über this in der gesamten Klasse nutzbar.

                                    
                                       constructor(private Func: FunctionsObjectService) {
                                       }
                                    

                                    dedlfix.

                              2. Bau lieber einen Service für die Formeln,und lass dir die benötigten per DI reinreichen

                                Genau das ist ja mein Problem. für Daten habe ich reichlich etwas gefunden, aber nicht vergleichbares mit Formeln. Oder ich bin ein Blindfisch?!

                                Ich wäre glücklich wenn Du mir ein kurzes Beispiel geben könntest, oder wo das nachlesen könnte.

                                Vor allem dachte ich mit:

                                constructor(Func: FunctionsObjectService) { this.Func = Func;

                                habe ich die DI.

                                Und meine Funktionen sind "sauber" ohne this. oder sonstigen Probleme wer oder woher diese aufgerufen hat bzw. wurde.

                                1. Angular Projekt Rohdaten

                                2. Tach!

                                  Bau lieber einen Service für die Formeln,und lass dir die benötigten per DI reinreichen

                                  Genau das ist ja mein Problem. für Daten habe ich reichlich etwas gefunden, aber nicht vergleichbares mit Formeln. Oder ich bin ein Blindfisch?!

                                  Ob Daten oder Funktionalität, für beides sind Services vorgesehen, sie zu beschaffen respektive bereitzustellen. Einzelne Funktionen werden meist nicht benötigt, aber natürlich kannst du solche problemlos verwenden. Auch vanilla-javascript-like als First Class Citizen. Aber mit Services hast du mehr Möglichkeiten, weil sie vom Infrastruktursystem von Angular unterstützt werden, und auch weil du mit einer Klasse deutlich mehr anstellen kannst, als mit einer Funktion.

                                  dedlfix.

                                  1. Moin Moin dedlfix,

                                    vielleicht verstehe und gebrauche ich manche Begriffe falsch? Im Grunde habe ich doch wie von mir beschrieben, den Service als Klasse benutzt. DIe "Funktionen" sind doch im Sinne eine Klassen-Methode, oder?

                                    1. Tach!

                                      vielleicht verstehe und gebrauche ich manche Begriffe falsch? Im Grunde habe ich doch wie von mir beschrieben, den Service als Klasse benutzt. DIe "Funktionen" sind doch im Sinne eine Klassen-Methode, oder?

                                      Ja, und genauso klassisch OOP sollte man das anwenden, wenn man nicht die Fallstricke umschiffen möchte, wenn man Methoden wie einfache Funktionen zu referenzieren versucht.

                                      dedlfix.

                                      1. Moin Moin,

                                        die Verlockung bei JS war groß, mit Funftionen zu arbeiten, weil der this. Bezug sich auf den aufrufenden Kontext bezieht. Aber spätestens bei der Button Umschaltung der Einheitsgrößen (mm,cm. N, kg)stößt das Ganze an die Grenzen. Daher werde ich es nun doch "wieder" über Klassenobjekte und Objektübergaben (nicht nur einzelne Variablenwerte) lösen.

                                        Weihnachtliche Grüße

                                        Jürgen

                                        1. Tach!

                                          die Verlockung bei JS war groß, mit Funftionen zu arbeiten, weil der this. Bezug sich auf den aufrufenden Kontext bezieht.

                                          Und das kann auch der Nachteil daran sein, wenn du Methoden von einem Angular-Service (oder irgendeiner anderen Klasse) direkt referenzierst, da ist das this nicht mehr das vom Service. Da ist der Service nur ein Sammelbecken von Funktionen, so wie beim Math-Objekt. Mit this würde ich da nicht mehr arbeiten wollen. Dinge, die erst zur Laufzeit gesetzt sind, können schlecht von der IDE erkannt und unterstützt werden.

                                          dedlfix.

                                          1. Ja, deshalb bin ich ja auch auf ANGULAR gekommen, denn JS war nie mein Favorit ist/war. Und mit Typescript und Doppelbindung hoffte ich etwas vom C# übernehmen zu können und meine Tools in meiner Homepage auszuführen.

                                            Sobald ich etwas Brauchbares fertig habe, werde ich es gerne hier zur Diskussion stellen.

                                            Grüße

                                            Juergen

                                            1. Formelsammlung in Angular effektiv aufbauen!? vorweg ich bin ein Newbi im Angular.

                                              1. Im HTML Teil soll nur das GUI aufgebaut werden.

                                              2. In der dazugehörigen @component soll nur:
                                                a) Festlegen der Varialblen als Properties und über {{Doppelbindung}} mit dem HTML Template verbinden. b) Diese Properties über einen Funktionsaufruf an de Service weitergereicht werden.

                                              3)Im Service soll dann eine der vielen Formel stehen, und innerhalb der gesamten App zur Verfügung stehen.

                                              Der Code im Einzelen:

                                              .... .component.ts:
                                              
                                              import { Component, OnInit } from '@angular/core';
                                              import { FunctionsObjectService } from '../../Services/functions-object.service';
                                              import { VariablenObjectService } from '../../Services/variablen-object.service';
                                              
                                              @Component({
                                                selector: 'app-home-page',
                                                templateUrl: './home-page.component.html',
                                                styleUrls: ['./home-page.component.css']
                                              })
                                              export class HomePageComponent implements OnInit {
                                              tileOfPage = 'HomePage';
                                              
                                              A = new VariablenObjectService('A', 5);
                                              B = new VariablenObjectService('B', 2);
                                              
                                                 constructor(private Func: FunctionsObjectService) { }
                                                 ngOnInit() {}
                                              
                                                // Hier hönnen mehrere Eigenschaften manipuliert werden.
                                                  half(objX: VariablenObjectService, objY: VariablenObjectService): void {this.Func.half(objX, objY); }
                                              
                                                // Hier wird expliziet nur ein Wert geändert.
                                                  doppel(objX: VariablenObjectService, objY: VariablenObjectService): void {objX.wert = this.Func.double(objX, objY); }
                                              }
                                              

                                              variablen-object.service.ts:

                                              import { Injectable } from '@angular/core';
                                              
                                              @Injectable({
                                                providedIn: 'root'
                                              })
                                              export class VariablenObjectService {
                                              
                                                public name = 'NA';
                                                public wert = 0;
                                              
                                                constructor(VariablenNamen: string, Wert: number) {
                                                  this.name = VariablenNamen;
                                                  this. wert = Wert; }
                                              }
                                              
                                              

                                              Functions-object.service.ts:

                                              import { Injectable } from '@angular/core';
                                              import {VariablenObjectService} from './variablen-object.service';
                                              
                                              @Injectable({
                                                providedIn: 'root'
                                              })
                                              export class FunctionsObjectService {
                                              
                                                constructor() {}
                                              
                                                double(x: VariablenObjectService, y?: VariablenObjectService) {return y.wert * 2; }
                                                half(x: VariablenObjectService, y?: VariablenObjectService) {y.wert =  y.wert / 2; x.wert = x.wert * 4; }
                                              }
                                              
                                              

                                              MEINE FRAGE:

                                              ist diese Übergabeart wirklich sinnvoll?

                                              half(objX: VariablenObjectService, objY: VariablenObjectService): void {this.Func.half(objX, objY); } ??