Michael
Michael

Reputation: 297

How to create material cards on button click?

I'm trying to create mat-cards when clicking on a button.

This is the information, which should be in the mat-card (this information comes from a service).

blockHash: "iejg5gpylg6l9gjxor3bnvigs0ipaonr"

blockNumber: 1

previousBlock: "00000000000000000000000000000000"

transactions: Array (1)
0 {sender: "10", recipient: null, amount: null, fee: null}

At the beginning the section, where the mat cards are at should be completely empty. When clicking on a button, that section should be filled with one mat-card; when clicking again, a second mat-card should appear and so on.

This is the block with the information (in another component), which gets send to the component, which should add up the material cards.

enter image description here

This is how it should look like (This is just hardcoded at the moment).

enter image description here

What's an elegant way to do that?

Upvotes: 2

Views: 8315

Answers (2)

frido
frido

Reputation: 14109

You should create a parent-component that displays multiple card-components.

https://stackblitz.com/edit/angular-zvjblo

parent-component

The parent-component holds your list of blocks and displays multiple card-components by supplying each card-component with the block data for that card. There is also a button to add a new block to the list.

template

<button (click)="addCard()">Add Card</button>
<app-block-card *ngFor="let block of blocks" [blockData]="block"></app-block-card>

code

import { Component, OnInit } from '@angular/core';
import { BlockData } from './block-data';

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

  blocks: BlockData[];

  ngOnInit() {
    this.blocks = [];
  }

  addCard() {
    this.blocks.push({
      blockHash: '9348534985720587',
      blockNumber: 3,
      previousBlock: "0000",
      transactions: [
        {
          sender: 'sender',
          recipient: 'recipient',
          amount: 1,
          fee: 200
        }
      ]
    });
  }

}

card-component

The card-component receives the data of one block from the parent component and displays it.

template

<mat-card class="card">
  <p>{{blockData.blockHash}}</p>
  <p>{{blockData.blockNumber}}</p>
  <p>{{blockData.previousBlock}}</p>
  <p>{{blockData.transactions | json}}</p>
</mat-card>

code

import { Component, OnInit, Input } from '@angular/core';
import { BlockData } from '../block-data';

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

  @Input() blockData: BlockData;

  constructor() { }

  ngOnInit() {
  }

}

Upvotes: 2

Skdy
Skdy

Reputation: 290

You could be using a list, but I am not sure how to make it horizontal so that might require some tweaking.

But, I would say a drag and drop list would also be very fitting. The documentation easily describes how to apply these with a horizontal view. But if the drag and drop feature is not for you, then the go with the list.

Using either you can run a *ngFor loop that can be performed upon arrays of data.

Example of such:

    <div cdkDropList cdkDropListOrientation="horizontal" class="example-list" 
    (cdkDropListDropped)="drop($event)">
      <div class="example-box" *ngFor="let card of cardArray" cdkDrag>
        <mat-card class="example-card">
          <mat-card-header>
            <div mat-card-avatar class="example-header-image"></div>
            <mat-card-title>Shiba Inu</mat-card-title>
            <mat-card-subtitle>Dog Breed</mat-card-subtitle>
          </mat-card-header>
          <img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
          <mat-card-content>
            <p>
             text
            </p>
          </mat-card-content>
          <mat-card-actions>
            <button mat-button>LIKE</button>
            <button mat-button>SHARE</button>
          </mat-card-actions>
        </mat-card>
      </div>
    </div>

In your case you will have to apply the card template inside the *ngFor div, and bind the data accordingly to your naming.

To add a new cards through a button you will simply have to add a new element to the array that you loop over, and it will appear when it has been added.

Upvotes: 0

Related Questions