简体   繁体   中英

How can i pass multiple variables from one component to the service in angular 9?

How can i pass multiple variables from one component to the service and get it in another component in angular 9 ? I tried so hard to solve this problem but I couldn't find any solution. I am trying to pass/send variable that contains some data from sendComponent to service and get that same data to another receiveComponent. After clicking button on send.Html and also navigate to receiveComponent.

sent.Html: I want to push data after pressing OK button from this html

<button class="btn btn-primary pull-right" (click)="onPushData()">
   <i class="fa fa-check" aria-hidden="true"></i> 
    OK
</button>

sendComponent: secondTableData,totalPrice and totalPrice these are the variables that contains data that needs to pass to service.ts May be this is wrong approach

onPushData(){                          
    let tData = this.secondTableData  // want to push secondTableData variable
    let t = this.totalPrice;          // want to push totalPrice variable
    let d = this.totalPrice           // want to push totalQuantity variable
    this.dataShareService.onPushTable(tData);
    console.log(tData);
    this.routerService.navigate(['./billprint'])
  }

Service.ts:

@Injectable({
  providedIn: 'root'
}) 

export class DataShareService { 

  onPushTable(tData) {
  --Do something here--
  }
 }

receiveComponent: i want to get data in this component

recDataFromService() {
  --do something here--
}

receive.Html: display data here

<tr *ngFor="let data of recData;let i = index">
   <td>{{i+1}}</td>
   <td>{{data.itemName}}</td>
   <td>{{data.Quantity}}</td>
   <td>{{data.retailRate}}</td>
</tr>

Help me to Solve this problem plz... Share your answer if u know any idea about this..

Sample: This is the code that contain the array of data(itemName, Quantity,retailRate ....) in secondTableData

  //To Copy data of First table to Second table
   secondTableData = [];
   updateSecondTable(data) {
   let foundItem = this.secondTableData.find((item) => item.itemName === 
     data.itemName);
   if (foundItem) {
    foundItem.rate = data.retailRate;
   foundItem.Quantity += 1;
   foundItem.retailRate += data.retailRate;
   this.getColumnTotal();   //  <----- To call total Price
   return;
   }
    this.secondTableData.push({
    itemName: data.itemName,
    rate:data.retailRate,
    Quantity: 1,
    retailRate: data.retailRate,
   })

   this.getColumnTotal();
  }

   // to calculate total amount
   getColumnTotal() {
   const { Quantity, Price } = this.secondTableData.reduce((acc, item) => 
     {
   acc.Quantity += item.Quantity;
   acc.Price += item.retailRate;
   return acc;
   }, {
   Quantity: 0,
   Price: 0
  });
  this.totalQuantity = Quantity;
  this.totalPrice = Price;
  }

Receive.html: This is the code where I want to display data in array

I want to push these variables(secondTableData, totalQuantity, TotalPrice...) in receive component and want to display it in tabular form.

<table class="table table-bordered table-sm">
  <thead>
    <tr>
        <th>SN</th>
        <th>Product</th>
        <th>Unit</th>
        <th>Price</th>
        <th>Total</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let recData of myData;let i = index">  <!--i want to display here -->
        <td>{{i+1}}</td>
        <td>{{recData.itemName}}</td>
        <td>{{recData.Quantity}}</td>
        <td>{{recData.retailRate}}</td>
        <td></td>
        
    </tr>
    <tr class="small" style="height: 10px;">
        <td colspan="3" style="border: none;"></td>
        <td>Gross Amount:</td>
        <td>1100</td>
    </tr>
    <tr class="small">
        <td colspan="3" style="border: none;"></td>
        <td>Discount:</td>
        <td>100</td>
    </tr>
    <tr class="small">
        <td colspan="3" style="border: none;"></td>
        <td>VAT</td>
        <td>30</td>
     </tr>
     <tr class="small">
        <td colspan="3" style="border: none;"></td>
        <td>Net Amont</td>
        <td>1030</td>
      </tr>
    </tbody>
</table>

You can create a transfer object containing everything you want (if you wish to send all of the variables using a single call):

const tData = this.secondTableData; variable
const t = this.totalPrice;
const d = this.totalQuantity;

const obj = {tData, t, d};
    
this.dataShareService.onPushTable(obj);

Then on your service:

@Injectable({providedIn: 'root'}) 
export class DataShareService {
  private yourData;

  onPushTable(obj) {
    this.yourData = obj;
  }

  getYourData() {
    return this.yourData;
  }
}

And in your component:

recDataFromService() {
  this.myData = this.dataShareService.getYourData();
}

[UPDATE PER COMMENTS]

The above answer isn't wrong at all => without further information, I think you're just trying to get the data at the wrong place/moment. To avoid this problem, you should adopt a reactive approach in the service:

@Injectable({providedIn: 'root'}) 
export class DataShareService {
  private _yourData$: BehaviorSubject<{tData:any[];t:number;d:number}> =
      new BehaviorSubject<{tData:any[];t:number;d:number}>({tData:[],t:0,d:0});

  onPushTable(obj) {
    this._yourData$.next(obj ? obj : {tData:[],t:0,d:0});
    // if you're using ts >= 3.9.x you can use:
    // this._yourData$.next(obj??{tData:[],t:0,d:0});
  }

  getYourData$(): Observable<{tData:any[];t:number;d:number}> {
    return this._yourData$.asObservable();
  }
}

On the receiving component typescript file:

_fromFirstComponent$: Observable<{tData:any[];t:number;d:number}> = 
    this._dataService.getYourData$();

constructor(private _dataService: DataShareService){}

And, in your receiving template:

...
<tbody>
    <tr *ngFor="let recData of (_fromFirstComponent$ | async)?.tData;let i = index">  <!--i want to display here -->
        <td>{{i+1}}</td>
        <td>{{recData.itemName}}</td>
        <td>{{recData.Quantity}}</td>
...

Any variable stored in your service will be visible in other component if you inject its service on it.

In your case, on onPushData , store everything you want in your service. I don't know exactly what you want, but will be something like:

onPushData(){                          
  let tData = this.secondTableData;
  let t = this.totalPrice;          
  let d = this.totalPrice;           
  this.dataShareService.onPushTable(tData, t, d);
  this.routerService.navigate(['./billprint'])
}

Be sure your service recieves all three variables and store it on it (for example, create those variables tdata, t and d on your service and get it on onPushTable .

So, inject your service on the second component constructor:

constructor(private myService:MyService)

Then, it will be available on:

console.log(this.myService.tData);
console.log(this.myService.t);
console.log(this.myService.d);

In your service:

@Injectable({
  providedIn: 'root'
}) 

export class DataShareService {
  private subject = new Subject<any>();

  onPushTable(data) {
    this.subject.next(data);
  }

  getData(): Observable<any> {
    return this.subject.asObservable();
  }
}

In your sendComponent :

this.dataShareService.onPushTable({tData, t, d});

In your receiveComponent :

this.service.getData().subscribe(data => this.data = data);

Then use the data field in your HTML template like:

<div>{{data.t}}</div>
<div>{{data.d}}</div>
<tr *ngFor="let rec of data.tData;let i = index">
   <td>{{i+1}}</td>
   <td>{{rec.itemName}}</td>
   <td>{{rec.Quantity}}</td>
   <td>{{rec.retailRate}}</td>
</tr>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM