LightBlog
Showing posts with label HTML. Show all posts
Showing posts with label HTML. Show all posts

Monday, 28 December 2020

Angular share data between parent child components using @Input and @Output decorators

December 28, 2020 0
Angular share data between parent child components


Last chapter we have discussed how we can share data between two unrelated components using behavioral subjects in Angular 8. Today I am going to explain how you can make an interaction between parent and child component using Angular.

Before moving forward, I will generate one component in my flower store angular app. Flower store is the app we used to demonstrate the angular concept talked in series of chapters in this blog. 

To generate the component, please run below ng CLI command in your command prompt. 

ng g c flower-card

Above command will generate the flower-card.component.ts and corresponding html and CSS files as below.


run cli command ng g c flower-card to generate the component in angular

Angular Related Articles:


In our flower app component landing page view has cards for each flower as below.

landing page of my flower store angular app


Currently your landing.component.html includes all the code to display cards. Below commented lines used to shows cards for each flower. 


<h1>Welcome to my flower store</h1>

    <div *ngFor="let flower of myFlowerList;trackBy:trackFlowers">
        <!-- <p-card header="{{flower.name}}"  [style]="{width: '360px','float':'left','margin-bottom': '2em','margin-right': '2em','background-color':'light-pink'}" styleClass="p-card-shadow">
                <img alt="Card" width="100" height="100" src="assets/stock/{{flower.name}}.jpg">
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt
                quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!</p>
                <p-checkbox name="flower" [style]="{'margin-top': '2em'}" value="{{flower.name}}" label="Order Now" [(ngModel)]="selectedFlowers"></p-checkbox>
             
            </p-card> -->
    </div>

    <div>Your search text is: {{searchText}}</div>

    <ul>
        <li *ngFor="let selectedFlower of selectedFlowers">
            <input id="select-user" type="checkbox" (change)="onCheckboxChange(selectedFlower,$event)"> {{selectedFlower}}

        </li>
    </ul>


I am going to replace commented lines by adding selected tags of flower-card component and I am going to move card displaying logic in to flower-card.component.html.

<h1>Welcome to my flower store</h1>

    <div *ngFor="let flower of myFlowerList;trackBy:trackFlowers">
      <flower-card></flower-card>
    </div>

    <div>Your search text is: {{searchText}}</div>

    <ul>
        <li *ngFor="let selectedFlower of selectedFlowers">
            <input id="select-user" type="checkbox" (change)="onCheckboxChange(selectedFlower,$event)"> {{selectedFlower}}

        </li>
    </ul>

<flower-card> is a selector tag in the flower-card component file. Below is the flower-card.component.ts file code for you to understand.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'flower-card', // selector 
  templateUrl: './flower-card.component.html',
  styleUrls: ['./flower-card.component.scss']
})
export class FlowerCardComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }
}


Now if I run my app you will see below screen because I still did not add any codes to flower-card.component.html file to shows flowers as a card.

flower-card.component.html file to shows flowers as a card

Pass data between parent component to child component in Angular

Now let’s focus on how to pass data from parent component (landing.component.ts) to child component (flower-card.component.ts). 

Now my flower array is defined inside the parent component and I am going to display data in child component. Now I must find a way to transfer data from parent to child component. 

In this case, we send the data from the parent component to the child component using an attribute. This attribute can then be accessed within the child component using the @input decorator.

Properties I need to pass from parent to child are only title or name of the flower since I used dummy text to display description.

I am using the title to read the image also. 

Now let us check how we can bind the attributes to child component from parent component below. There are two ways you can bind data.

<flower-card title="{{flower.name}}"></flower-card>

OR

<flower-card [title]="flower.name"></flower-card>

You can bind another attribute like description as below.

<flower-card [title]="flower.name" [description]="flower.description"></flower-card>

<h1>Welcome to my flower store</h1>

    <div *ngFor="let flower of myFlowerList;trackBy:trackFlowers">
      <!-- <flower-card title="{{flower.name}}"></flower-card> -->
      <flower-card [title]="flower.name"></flower-card>
   </div>

    <div>Your search text is: {{searchText}}</div>

    <ul>
        <li *ngFor="let selectedFlower of selectedFlowers">
            <input id="select-user" type="checkbox" (change)="onCheckboxChange(selectedFlower,$event)"> {{selectedFlower}}

        </li>
    </ul>


Now we have banded data from parent component to child component. Let us see how we can read these data from child component <flower-card-component>

To read data you should defined @Input() decorators. You need to import Input decorator from @angular/core to use @Input.

@Input() title:string =''

flower-card.component.ts file code.

import { Component, Input, OnInit } from '@angular/core';

@Component({
  selector: 'flower-card', // selector 
  templateUrl: './flower-card.component.html',
  styleUrls: ['./flower-card.component.scss']
})
export class FlowerCardComponent implements OnInit {

  constructor() { }
  
  @Input() title:string =''
  
  ngOnInit() {
  
  }
}}

Then I will copy paste commented code in parent component html (landing.component.html) file to child component html file and alter the file to display @input type variable value. (flower-card-component.html).

Since I am using PrimeNG component to display card and checkbox I will import PrimeNG modules in flower-card.component.ts file. Then I will move card style related code from landing.component.sccs to flower-card.component.scss file.

flower-card.component.html code:

<p-card header="{{title}}"  [style]="{width: '360px','float':'left','margin-bottom': '2em','margin-right': '2em','background-color':'light-pink'}" styleClass="p-card-shadow">
    <img alt="Card" width="100" height="100" src="assets/stock/{{title}}.jpg">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt
        quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!</p>
    <p-checkbox name="flower" [style]="{'margin-top': '2em'}" value="{{title}}" label="Order Now" [(ngModel)]="selectedFlowers"></p-checkbox>
</p-card>

flower-card.component.scss code:

.ui-card-title{
    background-color: lightpink !important;
}

.ui-chkbox-label{
    vertical-align:bottom;
}

Pass data between child component to parent component in Angular

In our previous application when user click on the checkboxes in each card checkbox value is bonded to the array using ngModel. So selected flower names will be stored in an array and you can directly print the value by iterating the array.

Now our checkbox is in child component and our printing logic is in parent component. So, you need to find a way to print the value when and checkbox checked event called in the child component.

To have child to parent communication we can capture the change in data due to any event within the child component. This event is then propagated to the parent component using the @Output decorator and Eventemitter.

First, I will define the object as below.

@Output() selectedFlower = new EventEmitter<string>();

To use @Output and EventEmitter you must import EventEmitter and Output component from @angular/core library.

In flower-card.component.html file I have added the check box change event. So, I can capture that event and emit it value to parent component as below. Since I used PrimeNG checkbox you must use (onChange) event.

<p-card header="{{title}}"  [style]="{width: '360px','float':'left','margin-bottom': '2em','margin-right': '2em','background-color':'light-pink'}" styleClass="p-card-shadow">
    <img alt="Card" width="100" height="100" src="assets/stock/{{title}}.jpg">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt
        quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!</p>
    <p-checkbox name="flower" [style]="{'margin-top': '2em'}" value="{{title}}" label="Order Now" (onChange)="selectCheckBox($event,title)" [(ngModel)]="selectedFlowers"></p-checkbox>
</p-card>

Then I am going to define the selectCheckBox event in flower-card.component.ts to emit the selected value.

selectCheckBox(value,name){
    this.selectedFlower.emit(name);
  }

import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import {CardModule} from 'primeng/card';
import {CheckboxModule} from 'primeng/checkbox';

@Component({
  selector: 'flower-card', // selector 
  templateUrl: './flower-card.component.html',
  styleUrls: ['./flower-card.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class FlowerCardComponent implements OnInit {

  constructor() { }

  @Input() title:string =''
  selectedFlowers: string[] = [];
  @Output() selectedFlower = new EventEmitter<string>();

  
  ngOnInit() {
  
  }

  selectCheckBox(value,name){
    this.selectedFlower.emit(name);
  }
}

Now we have implemented the code in child component. Let’s see how you can capture this emitted value and print it in a parent component.

For that you must bind the emitted event in a child component selected tag as below.

<flower-card [title]="flower.name" (selectedFlower)="printOrder($event)"></flower-card>

Here the bind event name should be same as the @Output name we defined in child component.
So now whenever user click on child component checkboxes that event is emitted to the parent component and printOrder() method defined in parent component will be executed. $event argument will contain the emitted value.

Inside the printOrder() method I have implemented the logic to check values is exist, if exist value will be remove from the array and if not value will be added to the array.

printOrder(flowerName){
    if(this.selectedFlowers.indexOf(flowerName)<0){
      this.selectedFlowers.push(flowerName)
    }
    else{
      let index = this.selectedFlowers.indexOf(flowerName);
      this.selectedFlowers.splice(index,1);
    }
}

Parent component code:

<h1>Welcome to my flower store</h1>

    <div *ngFor="let flower of myFlowerList;trackBy:trackFlowers">
      <flower-card [title]="flower.name" (selectedFlower)="printOrder($event)"></flower-card>
       </div>

    <div>Your have selected: {{searchText}}</div>

    <ul>
        <li *ngFor="let selectedFlower of selectedFlowers">
             {{selectedFlower}}

        </li>
    </ul>


import { Component, EventEmitter, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { flower } from '../../domain/flower';
import { DataService } from 'src/app/services/data.service';

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

  myFlowerList:flower[]=[];
  selectedFlowers: string[] =[];

  checkedList:string[]=[];
  searchText:string='';
  constructor(private dataService:DataService) { }

  ngOnInit() {
    this.mySellingFlowers();
    this.dataService.getSearchText().subscribe(response => {
      this.printSearchtext(response);
    })
  }

  printSearchtext(searchText){
    this.searchText = searchText;
  }

  printOrder(flowerName){
    if(this.selectedFlowers.indexOf(flowerName)<0){
      this.selectedFlowers.push(flowerName)
    }
    else{
      let index = this.selectedFlowers.indexOf(flowerName);
      this.selectedFlowers.splice(index,1);
    }

  }

  mySellingFlowers(){
    let rose = new flower();
    rose.name = "Rose";
    rose.price = 100;
    rose.availableQuantity = 1000;
    rose.isChecked = false;
    this. myFlowerList.push(rose);

    let lily = new flower();
    lily.name = "Lilly";
    lily.price = 80;
    lily.availableQuantity = 2000;
    lily.isChecked = false;
    this. myFlowerList.push(lily);

    let tulip = new flower();
    tulip.name = "Tulip";
    tulip.price = 100;
    tulip.availableQuantity = 2300;
    lily.isChecked = false;

    this. myFlowerList.push(tulip);

    let carnation = new flower();
    carnation.name = "Carnation";
    carnation.price = 50;
    carnation.availableQuantity = 1500;
    lily.isChecked = false;

    this. myFlowerList.push(carnation);

    let gerbera = new flower();
    gerbera.name = "Gerbera";
    gerbera.price = 50;
    gerbera.availableQuantity = 1500;
    lily.isChecked = false;

    this. myFlowerList.push(gerbera);

    let orchid = new flower();
    orchid.name = "Orchid";
    orchid.price = 50;
    orchid.availableQuantity = 1500;
    lily.isChecked = false;

    this. myFlowerList.push(orchid);

  }

  trackFlowers(index,flower){
    return flower?flower.name:undefined
  }
}

Now see the magic in your browser by clicking on the checkboxes.

click on checkboxes to select items in store


You can find complete source code related to the angular implementation we have done so far here in GitHub.



Sunday, 6 December 2020

How to draw a Circle using HTML and CSS?

December 06, 2020 0
How to draw a Circle using HTML and CSS?


 

It is very easy to draw shapes in HTML web page using CSS, for various applications. This is very common requirement for many UI developers to come up with elegant web pages to suit your client requirements. There are many ways to draw UI component on the HTML web page, there are different framework support different methods to draw. But you can easily draw Shapes on HTML web page using CSS and almost every web browser is capable of rendering without any issue. But if you use some frameworks to design your web UI, there might have some limitations specially for different browsers.

 

In this example I am going to draw a Circle on your webpage. There are two sections that you need to add to complete this task. First you need to add HTML component, where the object actually resides on the web page. Next is to change the look and feel of the HTML component to see like Circle. We call it as change the style. For that we need apply some style using CSS.

Here is the HTML page.


<html>

  <head>

  </head>

  <body>

    <div id="circle"></div>

  <body>

</html>


You have to define, HTML header and body parts. In the body part, we put a <DIV> to render our Circle shape.

 

<div id="circle"></div>

We give an ID called “circle” to our <DIV>. We can use this ID to refer our HTML component in CSS code to change the appearance of the component. If you have two HTML components you can give two different IDs and use them to refer in CSS code differently.

 Here is the CSS part.

 
<style>

      #circle {

            width: 50px;

            height: 50px;

            -webkit-border-radius: 25px;

            -moz-border-radius: 25px;

            border-radius: 25px;

            background: red;

          }

    </style>

Under header section of HTML page, you have to define your CSS style code.

<head></head>

 

#circle is referring to HTML DIV with ID “circle”, and apply above style to that component only. That is why we need to specify the DIV ID here.

Then we give height and width to 50 pixels, set border radius to 25 pixels and change background color of the circle to red. You can change these properties as you wish to change the look and feel of your circle.

 

Complete code:

 
<html>

  <head>

    <style>

      #circle {

            width: 50px;

            height: 50px;

            -webkit-border-radius: 25px;

            -moz-border-radius: 25px;

            border-radius: 25px;

            background: red;

          }

    </style>

  </head>

  <body>

    <div id="circle"></div>

  <body>

</html>

Above code generate, A HTML page with red circle.

 

 

A HTML page with red circle

LightBlog