Grab values from dynamic form content angularPrevent users from submitting a form by hitting EnterHow to prevent buttons from submitting formsForm values are not changing even on page reloadAngular/RxJs When should I unsubscribe from `Subscription`JavaScript - How to pass/store value from function to form hidden field?Angular 4 - using objects for option values in a select listAngular 5 get Material Select ValueDynamic mat-select option in form-arrayHorizontally aligning different types of material form control componentsnested forms and .control vs .value - help needed

Extension of 2-adic valuation to the real numbers

Was there a Viking Exchange as well as a Columbian one?

Can we say “you can pay when the order gets ready”?

Can an Area of Effect spell cast outside a Prismatic Wall extend inside it?

Why does nature favour the Laplacian?

How to stop co-workers from teasing me because I know Russian?

How to have a sharp product image?

Check if a string is entirely made of the same substring

What is the optimal strategy for the Dictionary Game?

Apply MapThread to all but one variable

Which big number is bigger?

How could Tony Stark make this in Endgame?

How to denote matrix elements succinctly?

can anyone help me with this awful query plan?

Was there a shared-world project before "Thieves World"?

555 timer FM transmitter

Does tea made with boiling water cool faster than tea made with boiled (but still hot) water?

What are the characteristics of a typeless programming language?

As an international instructor, should I openly talk about my accent?

Can SQL Server create collisions in system generated constraint names?

How to fry ground beef so it is well-browned

What happened to Captain America in Endgame?

If a planet has 3 moons, is it possible to have triple Full/New Moons at once?

How did Captain America manage to do this?



Grab values from dynamic form content angular


Prevent users from submitting a form by hitting EnterHow to prevent buttons from submitting formsForm values are not changing even on page reloadAngular/RxJs When should I unsubscribe from `Subscription`JavaScript - How to pass/store value from function to form hidden field?Angular 4 - using objects for option values in a select listAngular 5 get Material Select ValueDynamic mat-select option in form-arrayHorizontally aligning different types of material form control componentsnested forms and .control vs .value - help needed






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








3















I am working with a back-end API that I query for flight data, which I then loop over and display the data. My template code looks like this...



<form novalidate #form="ngForm">
<div class="flight-table">
<header fxLayout="row" fxLayoutAlign="space-between">
<div fxFlex="25">Flights</div>
<div fxFlex="17">Class</div>
<div fxFlex="18">Price (AED)</div>
<div fxFlex="15">PAX</div>
<div fxFlex="25">Total</div>
</header>

<main>
<div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between" *ngFor="let flight of data.flights; let i = index">
<p fxFlex="25">flight['flightName']</p>
<p fxFlex="17">flight['flightClass']</p>
<p fxFlex="18"> number</p>
<p fxFlex="15" fxLayout="column">
<mat-select placeholder="Ticket(s)">
<mat-option *ngFor="let pax of counter" [value]="pax"> pax </mat-option>
</mat-select>
</p>
<p fxFlex="25">AED 0</p>
</div>

<div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between">
<p class="capitalize" fxFlex="75"><strong>Total transport</strong></p>
<p class="center-text" fxFlex="25"><strong>AED 0</strong></p>
</div>
</main>
</div>
</form>


Flights table



When a user selects a number of tickets from the PAX dropdown, I'd like to update both the row total and the total transport. I'd need to be able to grab the value of the PAX select box and multiply it by flight['flightPrice'] but I can't quite figure out how to, because I can't know how many items are in the flights array. What you see is just one row but there could be more.



Also, I'd like to capture the value for each row. I've thought about adding a hidden form field for each row or sth like that. I'm not quite sure how to deal with this.
Is there some better way?



Update



I'm struggling with how to capture the selected rows. I've tried adding a hidden input field in each row like so..



<input 
matInput
[name]="flight['flightName']-flight['flightClass']-pax-flight['flightPrice']"
[value]="total"
ngModel>


That doesn't seem to work. The goal is to have each selected row stored in an object like so...
The dashes separate the flightName, flightClass, pax and flightPrice with the value being the total (pax * flightPrice) and pax the number of passengers.



flights: 
lufthansa-business-2-60: 120,
flyEmirates-first-3-50: 150



How should I go about it?










share|improve this question






























    3















    I am working with a back-end API that I query for flight data, which I then loop over and display the data. My template code looks like this...



    <form novalidate #form="ngForm">
    <div class="flight-table">
    <header fxLayout="row" fxLayoutAlign="space-between">
    <div fxFlex="25">Flights</div>
    <div fxFlex="17">Class</div>
    <div fxFlex="18">Price (AED)</div>
    <div fxFlex="15">PAX</div>
    <div fxFlex="25">Total</div>
    </header>

    <main>
    <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between" *ngFor="let flight of data.flights; let i = index">
    <p fxFlex="25">flight['flightName']</p>
    <p fxFlex="17">flight['flightClass']</p>
    <p fxFlex="18"> number</p>
    <p fxFlex="15" fxLayout="column">
    <mat-select placeholder="Ticket(s)">
    <mat-option *ngFor="let pax of counter" [value]="pax"> pax </mat-option>
    </mat-select>
    </p>
    <p fxFlex="25">AED 0</p>
    </div>

    <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between">
    <p class="capitalize" fxFlex="75"><strong>Total transport</strong></p>
    <p class="center-text" fxFlex="25"><strong>AED 0</strong></p>
    </div>
    </main>
    </div>
    </form>


    Flights table



    When a user selects a number of tickets from the PAX dropdown, I'd like to update both the row total and the total transport. I'd need to be able to grab the value of the PAX select box and multiply it by flight['flightPrice'] but I can't quite figure out how to, because I can't know how many items are in the flights array. What you see is just one row but there could be more.



    Also, I'd like to capture the value for each row. I've thought about adding a hidden form field for each row or sth like that. I'm not quite sure how to deal with this.
    Is there some better way?



    Update



    I'm struggling with how to capture the selected rows. I've tried adding a hidden input field in each row like so..



    <input 
    matInput
    [name]="flight['flightName']-flight['flightClass']-pax-flight['flightPrice']"
    [value]="total"
    ngModel>


    That doesn't seem to work. The goal is to have each selected row stored in an object like so...
    The dashes separate the flightName, flightClass, pax and flightPrice with the value being the total (pax * flightPrice) and pax the number of passengers.



    flights: 
    lufthansa-business-2-60: 120,
    flyEmirates-first-3-50: 150



    How should I go about it?










    share|improve this question


























      3












      3








      3








      I am working with a back-end API that I query for flight data, which I then loop over and display the data. My template code looks like this...



      <form novalidate #form="ngForm">
      <div class="flight-table">
      <header fxLayout="row" fxLayoutAlign="space-between">
      <div fxFlex="25">Flights</div>
      <div fxFlex="17">Class</div>
      <div fxFlex="18">Price (AED)</div>
      <div fxFlex="15">PAX</div>
      <div fxFlex="25">Total</div>
      </header>

      <main>
      <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between" *ngFor="let flight of data.flights; let i = index">
      <p fxFlex="25">flight['flightName']</p>
      <p fxFlex="17">flight['flightClass']</p>
      <p fxFlex="18"> number</p>
      <p fxFlex="15" fxLayout="column">
      <mat-select placeholder="Ticket(s)">
      <mat-option *ngFor="let pax of counter" [value]="pax"> pax </mat-option>
      </mat-select>
      </p>
      <p fxFlex="25">AED 0</p>
      </div>

      <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between">
      <p class="capitalize" fxFlex="75"><strong>Total transport</strong></p>
      <p class="center-text" fxFlex="25"><strong>AED 0</strong></p>
      </div>
      </main>
      </div>
      </form>


      Flights table



      When a user selects a number of tickets from the PAX dropdown, I'd like to update both the row total and the total transport. I'd need to be able to grab the value of the PAX select box and multiply it by flight['flightPrice'] but I can't quite figure out how to, because I can't know how many items are in the flights array. What you see is just one row but there could be more.



      Also, I'd like to capture the value for each row. I've thought about adding a hidden form field for each row or sth like that. I'm not quite sure how to deal with this.
      Is there some better way?



      Update



      I'm struggling with how to capture the selected rows. I've tried adding a hidden input field in each row like so..



      <input 
      matInput
      [name]="flight['flightName']-flight['flightClass']-pax-flight['flightPrice']"
      [value]="total"
      ngModel>


      That doesn't seem to work. The goal is to have each selected row stored in an object like so...
      The dashes separate the flightName, flightClass, pax and flightPrice with the value being the total (pax * flightPrice) and pax the number of passengers.



      flights: 
      lufthansa-business-2-60: 120,
      flyEmirates-first-3-50: 150



      How should I go about it?










      share|improve this question
















      I am working with a back-end API that I query for flight data, which I then loop over and display the data. My template code looks like this...



      <form novalidate #form="ngForm">
      <div class="flight-table">
      <header fxLayout="row" fxLayoutAlign="space-between">
      <div fxFlex="25">Flights</div>
      <div fxFlex="17">Class</div>
      <div fxFlex="18">Price (AED)</div>
      <div fxFlex="15">PAX</div>
      <div fxFlex="25">Total</div>
      </header>

      <main>
      <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between" *ngFor="let flight of data.flights; let i = index">
      <p fxFlex="25">flight['flightName']</p>
      <p fxFlex="17">flight['flightClass']</p>
      <p fxFlex="18"> number</p>
      <p fxFlex="15" fxLayout="column">
      <mat-select placeholder="Ticket(s)">
      <mat-option *ngFor="let pax of counter" [value]="pax"> pax </mat-option>
      </mat-select>
      </p>
      <p fxFlex="25">AED 0</p>
      </div>

      <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between">
      <p class="capitalize" fxFlex="75"><strong>Total transport</strong></p>
      <p class="center-text" fxFlex="25"><strong>AED 0</strong></p>
      </div>
      </main>
      </div>
      </form>


      Flights table



      When a user selects a number of tickets from the PAX dropdown, I'd like to update both the row total and the total transport. I'd need to be able to grab the value of the PAX select box and multiply it by flight['flightPrice'] but I can't quite figure out how to, because I can't know how many items are in the flights array. What you see is just one row but there could be more.



      Also, I'd like to capture the value for each row. I've thought about adding a hidden form field for each row or sth like that. I'm not quite sure how to deal with this.
      Is there some better way?



      Update



      I'm struggling with how to capture the selected rows. I've tried adding a hidden input field in each row like so..



      <input 
      matInput
      [name]="flight['flightName']-flight['flightClass']-pax-flight['flightPrice']"
      [value]="total"
      ngModel>


      That doesn't seem to work. The goal is to have each selected row stored in an object like so...
      The dashes separate the flightName, flightClass, pax and flightPrice with the value being the total (pax * flightPrice) and pax the number of passengers.



      flights: 
      lufthansa-business-2-60: 120,
      flyEmirates-first-3-50: 150



      How should I go about it?







      html angular angular-forms






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 10 at 9:49







      Nelson King

















      asked Mar 9 at 9:19









      Nelson KingNelson King

      1068




      1068






















          1 Answer
          1






          active

          oldest

          votes


















          2














          I would recommend that you create a dedicated component for your basket items.
          You then have an isolated scope you can work with and i.e. use [(ngModel)] to set the selected number of pax on your component (for which you have to import the FormsModule in your app/feature module).
          You can then reuse that value to compute the total price for a flight.



          To get the total for the entire transport (sum over all basket items), you'd also need to pass data between components. A BasketService that keeps track of your basket items can help with that. I created a little stackblitz to demonstrate how to do this: https://stackblitz.com/edit/angular-tpenou



          The relevant parts are:



          export class BasketItemComponent implements OnDestroy 

          @Input() flight: Flight;
          paxOptions = [0, 1, 2, 3, 4];
          pax = 0;

          constructor(private basketService: BasketService)
          this.basketService.registerBasketItemComponent(this);


          ngOnDestroy(): void
          this.basketService.removeBasketItemComponent(this);


          get total()
          return this.flight.flightPrice * this.pax;





          And the template:



          <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between" >
          <p fxFlex="25">flight['flightName']</p>
          <p fxFlex="17">flight['flightClass']</p>
          <p fxFlex="18"> number</p>
          <p fxFlex="15" fxLayout="column">
          <mat-select placeholder="Ticket(s)" [(ngModel)]="pax">
          <mat-option *ngFor="let pax of paxOptions" [value]="pax"> pax </mat-option>
          </mat-select>
          </p>
          <p fxFlex="25">AED total </p>
          </div>


          And the BasketService:



          export class BasketService 

          basketItems: BasketItemComponent[] = [];

          constructor()

          get total()
          return this.basketItems.reduce( (a, b) => a + b.total, 0);


          registerBasketItemComponent(c: BasketItemComponent)
          this.basketItems.push(c);


          removeBasketItemComponent(c: BasketItemComponent)
          this.basketItems.splice(this.basketItems.indexOf(c), 1);




          You would also have to alter your for loop to make use of your newly created custom component:



          <form novalidate #form="ngForm">
          <div class="flight-table">
          <header fxLayout="row" fxLayoutAlign="space-between">
          <div fxFlex="25">Flights</div>
          <div fxFlex="17">Class</div>
          <div fxFlex="18">Price (AED)</div>
          <div fxFlex="15">PAX</div>
          <div fxFlex="25">Total</div>
          </header>

          <main>
          <app-basket-item [flight]="flight" *ngFor="let flight of data.flights; let i = index">

          </app-basket-item>

          <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between">
          <p class="capitalize" fxFlex="75"><strong>Total transport</strong></p>
          <p class="center-text" fxFlex="25"><strong>AED transportTotal</strong></p>
          </div>
          </main>
          </div>
          </form>





          share|improve this answer

























          • Dude thank you so much for your answer. The solution seems much more involved than I had hoped it would be though. Could it be any shorter?

            – Nelson King
            Mar 9 at 15:21






          • 2





            @NelsonKing Of course you can do it in a shorter fashion, but it's not necessarily ideal from a maintainability perspective. Created an alternative version on stackblitz: stackblitz.com/edit/angular-yz1hqc

            – Jan Wendland
            Mar 9 at 15:34












          • I hear you. Thank you so much.

            – Nelson King
            Mar 9 at 17:31






          • 1





            @NelsonKing I adapted the latter stackblitz (stackblitz.com/edit/angular-yz1hqc) with a change listener on the pax element that populates a selectedFlights object on AppComponent when the number of pax changes. Have a look and let me know if you have any questions. (Note the console.log of this.selectedFlights which prints the object in the structure you desire)

            – Jan Wendland
            Mar 10 at 10:09







          • 1





            @NelsonKing Maybe typescript is ranting because the reduce is actually a combination of map and reduce and the type inference has issues with that. Does it work if you write it like this: this.data.flights.map(f => Number.parseFloat(f['flightPrice']) * (f['pax'] || 0)).reduce((total, flightPrice) => total + flightPrice, 0); ? If that's not the issue please fork my stackblitz and mock the data as it is returned from your API so I have somewhere to start from

            – Jan Wendland
            Mar 11 at 11:56












          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55075802%2fgrab-values-from-dynamic-form-content-angular%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          I would recommend that you create a dedicated component for your basket items.
          You then have an isolated scope you can work with and i.e. use [(ngModel)] to set the selected number of pax on your component (for which you have to import the FormsModule in your app/feature module).
          You can then reuse that value to compute the total price for a flight.



          To get the total for the entire transport (sum over all basket items), you'd also need to pass data between components. A BasketService that keeps track of your basket items can help with that. I created a little stackblitz to demonstrate how to do this: https://stackblitz.com/edit/angular-tpenou



          The relevant parts are:



          export class BasketItemComponent implements OnDestroy 

          @Input() flight: Flight;
          paxOptions = [0, 1, 2, 3, 4];
          pax = 0;

          constructor(private basketService: BasketService)
          this.basketService.registerBasketItemComponent(this);


          ngOnDestroy(): void
          this.basketService.removeBasketItemComponent(this);


          get total()
          return this.flight.flightPrice * this.pax;





          And the template:



          <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between" >
          <p fxFlex="25">flight['flightName']</p>
          <p fxFlex="17">flight['flightClass']</p>
          <p fxFlex="18"> number</p>
          <p fxFlex="15" fxLayout="column">
          <mat-select placeholder="Ticket(s)" [(ngModel)]="pax">
          <mat-option *ngFor="let pax of paxOptions" [value]="pax"> pax </mat-option>
          </mat-select>
          </p>
          <p fxFlex="25">AED total </p>
          </div>


          And the BasketService:



          export class BasketService 

          basketItems: BasketItemComponent[] = [];

          constructor()

          get total()
          return this.basketItems.reduce( (a, b) => a + b.total, 0);


          registerBasketItemComponent(c: BasketItemComponent)
          this.basketItems.push(c);


          removeBasketItemComponent(c: BasketItemComponent)
          this.basketItems.splice(this.basketItems.indexOf(c), 1);




          You would also have to alter your for loop to make use of your newly created custom component:



          <form novalidate #form="ngForm">
          <div class="flight-table">
          <header fxLayout="row" fxLayoutAlign="space-between">
          <div fxFlex="25">Flights</div>
          <div fxFlex="17">Class</div>
          <div fxFlex="18">Price (AED)</div>
          <div fxFlex="15">PAX</div>
          <div fxFlex="25">Total</div>
          </header>

          <main>
          <app-basket-item [flight]="flight" *ngFor="let flight of data.flights; let i = index">

          </app-basket-item>

          <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between">
          <p class="capitalize" fxFlex="75"><strong>Total transport</strong></p>
          <p class="center-text" fxFlex="25"><strong>AED transportTotal</strong></p>
          </div>
          </main>
          </div>
          </form>





          share|improve this answer

























          • Dude thank you so much for your answer. The solution seems much more involved than I had hoped it would be though. Could it be any shorter?

            – Nelson King
            Mar 9 at 15:21






          • 2





            @NelsonKing Of course you can do it in a shorter fashion, but it's not necessarily ideal from a maintainability perspective. Created an alternative version on stackblitz: stackblitz.com/edit/angular-yz1hqc

            – Jan Wendland
            Mar 9 at 15:34












          • I hear you. Thank you so much.

            – Nelson King
            Mar 9 at 17:31






          • 1





            @NelsonKing I adapted the latter stackblitz (stackblitz.com/edit/angular-yz1hqc) with a change listener on the pax element that populates a selectedFlights object on AppComponent when the number of pax changes. Have a look and let me know if you have any questions. (Note the console.log of this.selectedFlights which prints the object in the structure you desire)

            – Jan Wendland
            Mar 10 at 10:09







          • 1





            @NelsonKing Maybe typescript is ranting because the reduce is actually a combination of map and reduce and the type inference has issues with that. Does it work if you write it like this: this.data.flights.map(f => Number.parseFloat(f['flightPrice']) * (f['pax'] || 0)).reduce((total, flightPrice) => total + flightPrice, 0); ? If that's not the issue please fork my stackblitz and mock the data as it is returned from your API so I have somewhere to start from

            – Jan Wendland
            Mar 11 at 11:56
















          2














          I would recommend that you create a dedicated component for your basket items.
          You then have an isolated scope you can work with and i.e. use [(ngModel)] to set the selected number of pax on your component (for which you have to import the FormsModule in your app/feature module).
          You can then reuse that value to compute the total price for a flight.



          To get the total for the entire transport (sum over all basket items), you'd also need to pass data between components. A BasketService that keeps track of your basket items can help with that. I created a little stackblitz to demonstrate how to do this: https://stackblitz.com/edit/angular-tpenou



          The relevant parts are:



          export class BasketItemComponent implements OnDestroy 

          @Input() flight: Flight;
          paxOptions = [0, 1, 2, 3, 4];
          pax = 0;

          constructor(private basketService: BasketService)
          this.basketService.registerBasketItemComponent(this);


          ngOnDestroy(): void
          this.basketService.removeBasketItemComponent(this);


          get total()
          return this.flight.flightPrice * this.pax;





          And the template:



          <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between" >
          <p fxFlex="25">flight['flightName']</p>
          <p fxFlex="17">flight['flightClass']</p>
          <p fxFlex="18"> number</p>
          <p fxFlex="15" fxLayout="column">
          <mat-select placeholder="Ticket(s)" [(ngModel)]="pax">
          <mat-option *ngFor="let pax of paxOptions" [value]="pax"> pax </mat-option>
          </mat-select>
          </p>
          <p fxFlex="25">AED total </p>
          </div>


          And the BasketService:



          export class BasketService 

          basketItems: BasketItemComponent[] = [];

          constructor()

          get total()
          return this.basketItems.reduce( (a, b) => a + b.total, 0);


          registerBasketItemComponent(c: BasketItemComponent)
          this.basketItems.push(c);


          removeBasketItemComponent(c: BasketItemComponent)
          this.basketItems.splice(this.basketItems.indexOf(c), 1);




          You would also have to alter your for loop to make use of your newly created custom component:



          <form novalidate #form="ngForm">
          <div class="flight-table">
          <header fxLayout="row" fxLayoutAlign="space-between">
          <div fxFlex="25">Flights</div>
          <div fxFlex="17">Class</div>
          <div fxFlex="18">Price (AED)</div>
          <div fxFlex="15">PAX</div>
          <div fxFlex="25">Total</div>
          </header>

          <main>
          <app-basket-item [flight]="flight" *ngFor="let flight of data.flights; let i = index">

          </app-basket-item>

          <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between">
          <p class="capitalize" fxFlex="75"><strong>Total transport</strong></p>
          <p class="center-text" fxFlex="25"><strong>AED transportTotal</strong></p>
          </div>
          </main>
          </div>
          </form>





          share|improve this answer

























          • Dude thank you so much for your answer. The solution seems much more involved than I had hoped it would be though. Could it be any shorter?

            – Nelson King
            Mar 9 at 15:21






          • 2





            @NelsonKing Of course you can do it in a shorter fashion, but it's not necessarily ideal from a maintainability perspective. Created an alternative version on stackblitz: stackblitz.com/edit/angular-yz1hqc

            – Jan Wendland
            Mar 9 at 15:34












          • I hear you. Thank you so much.

            – Nelson King
            Mar 9 at 17:31






          • 1





            @NelsonKing I adapted the latter stackblitz (stackblitz.com/edit/angular-yz1hqc) with a change listener on the pax element that populates a selectedFlights object on AppComponent when the number of pax changes. Have a look and let me know if you have any questions. (Note the console.log of this.selectedFlights which prints the object in the structure you desire)

            – Jan Wendland
            Mar 10 at 10:09







          • 1





            @NelsonKing Maybe typescript is ranting because the reduce is actually a combination of map and reduce and the type inference has issues with that. Does it work if you write it like this: this.data.flights.map(f => Number.parseFloat(f['flightPrice']) * (f['pax'] || 0)).reduce((total, flightPrice) => total + flightPrice, 0); ? If that's not the issue please fork my stackblitz and mock the data as it is returned from your API so I have somewhere to start from

            – Jan Wendland
            Mar 11 at 11:56














          2












          2








          2







          I would recommend that you create a dedicated component for your basket items.
          You then have an isolated scope you can work with and i.e. use [(ngModel)] to set the selected number of pax on your component (for which you have to import the FormsModule in your app/feature module).
          You can then reuse that value to compute the total price for a flight.



          To get the total for the entire transport (sum over all basket items), you'd also need to pass data between components. A BasketService that keeps track of your basket items can help with that. I created a little stackblitz to demonstrate how to do this: https://stackblitz.com/edit/angular-tpenou



          The relevant parts are:



          export class BasketItemComponent implements OnDestroy 

          @Input() flight: Flight;
          paxOptions = [0, 1, 2, 3, 4];
          pax = 0;

          constructor(private basketService: BasketService)
          this.basketService.registerBasketItemComponent(this);


          ngOnDestroy(): void
          this.basketService.removeBasketItemComponent(this);


          get total()
          return this.flight.flightPrice * this.pax;





          And the template:



          <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between" >
          <p fxFlex="25">flight['flightName']</p>
          <p fxFlex="17">flight['flightClass']</p>
          <p fxFlex="18"> number</p>
          <p fxFlex="15" fxLayout="column">
          <mat-select placeholder="Ticket(s)" [(ngModel)]="pax">
          <mat-option *ngFor="let pax of paxOptions" [value]="pax"> pax </mat-option>
          </mat-select>
          </p>
          <p fxFlex="25">AED total </p>
          </div>


          And the BasketService:



          export class BasketService 

          basketItems: BasketItemComponent[] = [];

          constructor()

          get total()
          return this.basketItems.reduce( (a, b) => a + b.total, 0);


          registerBasketItemComponent(c: BasketItemComponent)
          this.basketItems.push(c);


          removeBasketItemComponent(c: BasketItemComponent)
          this.basketItems.splice(this.basketItems.indexOf(c), 1);




          You would also have to alter your for loop to make use of your newly created custom component:



          <form novalidate #form="ngForm">
          <div class="flight-table">
          <header fxLayout="row" fxLayoutAlign="space-between">
          <div fxFlex="25">Flights</div>
          <div fxFlex="17">Class</div>
          <div fxFlex="18">Price (AED)</div>
          <div fxFlex="15">PAX</div>
          <div fxFlex="25">Total</div>
          </header>

          <main>
          <app-basket-item [flight]="flight" *ngFor="let flight of data.flights; let i = index">

          </app-basket-item>

          <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between">
          <p class="capitalize" fxFlex="75"><strong>Total transport</strong></p>
          <p class="center-text" fxFlex="25"><strong>AED transportTotal</strong></p>
          </div>
          </main>
          </div>
          </form>





          share|improve this answer















          I would recommend that you create a dedicated component for your basket items.
          You then have an isolated scope you can work with and i.e. use [(ngModel)] to set the selected number of pax on your component (for which you have to import the FormsModule in your app/feature module).
          You can then reuse that value to compute the total price for a flight.



          To get the total for the entire transport (sum over all basket items), you'd also need to pass data between components. A BasketService that keeps track of your basket items can help with that. I created a little stackblitz to demonstrate how to do this: https://stackblitz.com/edit/angular-tpenou



          The relevant parts are:



          export class BasketItemComponent implements OnDestroy 

          @Input() flight: Flight;
          paxOptions = [0, 1, 2, 3, 4];
          pax = 0;

          constructor(private basketService: BasketService)
          this.basketService.registerBasketItemComponent(this);


          ngOnDestroy(): void
          this.basketService.removeBasketItemComponent(this);


          get total()
          return this.flight.flightPrice * this.pax;





          And the template:



          <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between" >
          <p fxFlex="25">flight['flightName']</p>
          <p fxFlex="17">flight['flightClass']</p>
          <p fxFlex="18"> number</p>
          <p fxFlex="15" fxLayout="column">
          <mat-select placeholder="Ticket(s)" [(ngModel)]="pax">
          <mat-option *ngFor="let pax of paxOptions" [value]="pax"> pax </mat-option>
          </mat-select>
          </p>
          <p fxFlex="25">AED total </p>
          </div>


          And the BasketService:



          export class BasketService 

          basketItems: BasketItemComponent[] = [];

          constructor()

          get total()
          return this.basketItems.reduce( (a, b) => a + b.total, 0);


          registerBasketItemComponent(c: BasketItemComponent)
          this.basketItems.push(c);


          removeBasketItemComponent(c: BasketItemComponent)
          this.basketItems.splice(this.basketItems.indexOf(c), 1);




          You would also have to alter your for loop to make use of your newly created custom component:



          <form novalidate #form="ngForm">
          <div class="flight-table">
          <header fxLayout="row" fxLayoutAlign="space-between">
          <div fxFlex="25">Flights</div>
          <div fxFlex="17">Class</div>
          <div fxFlex="18">Price (AED)</div>
          <div fxFlex="15">PAX</div>
          <div fxFlex="25">Total</div>
          </header>

          <main>
          <app-basket-item [flight]="flight" *ngFor="let flight of data.flights; let i = index">

          </app-basket-item>

          <div class="flights-body--row" fxLayout="row" fxLayoutAlign="space-between">
          <p class="capitalize" fxFlex="75"><strong>Total transport</strong></p>
          <p class="center-text" fxFlex="25"><strong>AED transportTotal</strong></p>
          </div>
          </main>
          </div>
          </form>






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 9 at 14:32

























          answered Mar 9 at 14:09









          Jan WendlandJan Wendland

          785415




          785415












          • Dude thank you so much for your answer. The solution seems much more involved than I had hoped it would be though. Could it be any shorter?

            – Nelson King
            Mar 9 at 15:21






          • 2





            @NelsonKing Of course you can do it in a shorter fashion, but it's not necessarily ideal from a maintainability perspective. Created an alternative version on stackblitz: stackblitz.com/edit/angular-yz1hqc

            – Jan Wendland
            Mar 9 at 15:34












          • I hear you. Thank you so much.

            – Nelson King
            Mar 9 at 17:31






          • 1





            @NelsonKing I adapted the latter stackblitz (stackblitz.com/edit/angular-yz1hqc) with a change listener on the pax element that populates a selectedFlights object on AppComponent when the number of pax changes. Have a look and let me know if you have any questions. (Note the console.log of this.selectedFlights which prints the object in the structure you desire)

            – Jan Wendland
            Mar 10 at 10:09







          • 1





            @NelsonKing Maybe typescript is ranting because the reduce is actually a combination of map and reduce and the type inference has issues with that. Does it work if you write it like this: this.data.flights.map(f => Number.parseFloat(f['flightPrice']) * (f['pax'] || 0)).reduce((total, flightPrice) => total + flightPrice, 0); ? If that's not the issue please fork my stackblitz and mock the data as it is returned from your API so I have somewhere to start from

            – Jan Wendland
            Mar 11 at 11:56


















          • Dude thank you so much for your answer. The solution seems much more involved than I had hoped it would be though. Could it be any shorter?

            – Nelson King
            Mar 9 at 15:21






          • 2





            @NelsonKing Of course you can do it in a shorter fashion, but it's not necessarily ideal from a maintainability perspective. Created an alternative version on stackblitz: stackblitz.com/edit/angular-yz1hqc

            – Jan Wendland
            Mar 9 at 15:34












          • I hear you. Thank you so much.

            – Nelson King
            Mar 9 at 17:31






          • 1





            @NelsonKing I adapted the latter stackblitz (stackblitz.com/edit/angular-yz1hqc) with a change listener on the pax element that populates a selectedFlights object on AppComponent when the number of pax changes. Have a look and let me know if you have any questions. (Note the console.log of this.selectedFlights which prints the object in the structure you desire)

            – Jan Wendland
            Mar 10 at 10:09







          • 1





            @NelsonKing Maybe typescript is ranting because the reduce is actually a combination of map and reduce and the type inference has issues with that. Does it work if you write it like this: this.data.flights.map(f => Number.parseFloat(f['flightPrice']) * (f['pax'] || 0)).reduce((total, flightPrice) => total + flightPrice, 0); ? If that's not the issue please fork my stackblitz and mock the data as it is returned from your API so I have somewhere to start from

            – Jan Wendland
            Mar 11 at 11:56

















          Dude thank you so much for your answer. The solution seems much more involved than I had hoped it would be though. Could it be any shorter?

          – Nelson King
          Mar 9 at 15:21





          Dude thank you so much for your answer. The solution seems much more involved than I had hoped it would be though. Could it be any shorter?

          – Nelson King
          Mar 9 at 15:21




          2




          2





          @NelsonKing Of course you can do it in a shorter fashion, but it's not necessarily ideal from a maintainability perspective. Created an alternative version on stackblitz: stackblitz.com/edit/angular-yz1hqc

          – Jan Wendland
          Mar 9 at 15:34






          @NelsonKing Of course you can do it in a shorter fashion, but it's not necessarily ideal from a maintainability perspective. Created an alternative version on stackblitz: stackblitz.com/edit/angular-yz1hqc

          – Jan Wendland
          Mar 9 at 15:34














          I hear you. Thank you so much.

          – Nelson King
          Mar 9 at 17:31





          I hear you. Thank you so much.

          – Nelson King
          Mar 9 at 17:31




          1




          1





          @NelsonKing I adapted the latter stackblitz (stackblitz.com/edit/angular-yz1hqc) with a change listener on the pax element that populates a selectedFlights object on AppComponent when the number of pax changes. Have a look and let me know if you have any questions. (Note the console.log of this.selectedFlights which prints the object in the structure you desire)

          – Jan Wendland
          Mar 10 at 10:09






          @NelsonKing I adapted the latter stackblitz (stackblitz.com/edit/angular-yz1hqc) with a change listener on the pax element that populates a selectedFlights object on AppComponent when the number of pax changes. Have a look and let me know if you have any questions. (Note the console.log of this.selectedFlights which prints the object in the structure you desire)

          – Jan Wendland
          Mar 10 at 10:09





          1




          1





          @NelsonKing Maybe typescript is ranting because the reduce is actually a combination of map and reduce and the type inference has issues with that. Does it work if you write it like this: this.data.flights.map(f => Number.parseFloat(f['flightPrice']) * (f['pax'] || 0)).reduce((total, flightPrice) => total + flightPrice, 0); ? If that's not the issue please fork my stackblitz and mock the data as it is returned from your API so I have somewhere to start from

          – Jan Wendland
          Mar 11 at 11:56






          @NelsonKing Maybe typescript is ranting because the reduce is actually a combination of map and reduce and the type inference has issues with that. Does it work if you write it like this: this.data.flights.map(f => Number.parseFloat(f['flightPrice']) * (f['pax'] || 0)).reduce((total, flightPrice) => total + flightPrice, 0); ? If that's not the issue please fork my stackblitz and mock the data as it is returned from your API so I have somewhere to start from

          – Jan Wendland
          Mar 11 at 11:56




















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55075802%2fgrab-values-from-dynamic-form-content-angular%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          1928 у кіно

          Захаров Федір Захарович

          Ель Греко