Tuesday 13 August 2024

new @let block in Angular templates



<div>
@let userName = (userName$ | async) ?? 'Guest'; <h1>Welcome, {{ userName }}</h1> </div>


<table mat-table [dataSource]="dataSource">
@for (columnDef of columnDefs) {
@let property = columnDef.propertyName;
<ng-container [matColumnDef]="columnDef.name">
<th mat-header-cell *matHeaderCellDef>{{ columnDef.header }}</th>
<td mat-cell *matCellDef="let element">
@let cellValue = element[property];
<ng-container *ngIf="columnDef.cellType === 'link'; else plainCell">
<a [routerLink]="cellValue?.routerLink">{{ cellValue?.value }}</a>
</ng-container>
<ng-template #plainCell>{{ cellValue }}</ng-template>
</td>
</ng-container>
}
</table>



<div>
@let firstName = user?.firstName;
@let lastName = user?.lastName;
@let fullName = `${firstName} ${lastName}`;
<p>{{ fullName }}</p>
@if (user?.address) {
@let street = user.address.street;
@let city = user.address.city;
<p>{{ street }}, {{ city }}</p>
}
</div>


Conclusion 

 @let syntax in Angular, combined with the new control flow features like @if and @for, offers a significant improvement for template variable declarations and control flow management. While some may argue for the continued use of signals for state management, the @let syntax provides an elegant solution for handling local variables within templates. By addressing common challenges such as managing falsy values, avoiding multiple subscriptions, and reducing repetitive code, this new feature is poised to enhance the development experience for Angular developers.


Saturday 29 June 2024

Exploring Macau: 4 to 5 Day Itinerary of Must-Visit Places

 ## Exploring Macau:  4-Day Itinerary of Must-Visit Places


### Introduction

Welcome to Macau, a vibrant blend of Portuguese heritage and modern architecture. This four-day itinerary will guide you through the most iconic and must-visit locations on both Taipa Island and the Main Macau Island. Prepare to be amazed by the grandeur of luxury hotels, historical landmarks, and cultural experiences that make Macau a unique travel destination.


### Day 1: Discover Taipa Island


#### The Parisian Macao

Kickstart your journey with a stay at The Parisian Macao. With its iconic Eiffel Tower replica, it offers a slice of Parisian charm right in Macau.


#### Venetian Macao Casino

Your first adventure starts at the Venetian Macao Casino, where you can enjoy a gondola ride through its canals, indulge in shopping, and try your luck at the casino.


#### The Londoner Macao

Next, head to The Londoner Macao. This British-themed complex brings the essence of London to Macau with its stunning architecture and themed attractions.


#### Grand Lisboa Palace Resort Macau

Continue your exploration with a visit to the Grand Lisboa Palace Resort Macau. Its luxurious ambiance and exquisite decor will leave you spellbound.


#### Sheraton Grand Macao

Take a moment to relax at the Sheraton Grand Macao, another stunning hotel offering world-class amenities and services.


#### TeamLab SuperNature Macau

Immerse yourself in the digital art world at TeamLab SuperNature Macau, where interactive installations and mesmerizing displays create a unique experience.


#### Galaxy Hotel - Fortune Diamond at Galaxy Macau

Conclude your day with a visit to the Galaxy Hotel and witness the Fortune Diamond show, a spectacular performance featuring a giant diamond emerging from a fountain.


#### The Ritz-Carlton, Macau

End your first day with a luxurious dinner at The Ritz-Carlton, Macau, known for its exceptional service and gourmet dining options.


### Day 2: More Wonders on Taipa Island


#### Studio City Macau

Start your second day with a stay at Studio City Macau, a Hollywood-themed resort offering entertainment, shopping, and dining options.


#### Wynn Palace

Visit Wynn Palace, famous for its stunning Performance Lake show and luxurious surroundings.


#### Taipa Houses-Museum

Explore the Taipa Houses-Museum, a collection of colonial-style houses showcasing Macau's history and culture.


#### Morpheus Building

Marvel at the architectural wonder of the Morpheus building, designed by the renowned architect Zaha Hadid.


#### City of Dreams Shopping Mall

Indulge in some retail therapy at the City of Dreams Shopping Mall, offering a variety of high-end stores and dining options.


#### The House of Dancing Water Show

Experience the mesmerizing House of Dancing Water Show, a spectacular performance featuring acrobatics, dance, and water effects.


#### Macao Giant Panda Pavilion

Take a short trip to the Macao Giant Panda Pavilion and enjoy the adorable sight of pandas in their natural habitat.


#### A-Ma Cultural Village

Visit the A-Ma Cultural Village to learn about Macau's rich cultural heritage and enjoy the serene surroundings.


#### Macau Sightseeing Cruise

End your day with a relaxing Macau Sightseeing Cruise, offering stunning views of the city skyline.


### Day 3: Unveil Main Macau Island


#### Hotel Royal Macau

Check into Hotel Royal Macau, strategically located near several major attractions.


#### Guia Fortress and Lighthouse

Start your day with a visit to Guia Fortress and Lighthouse, offering panoramic views of Macau.


#### Tap Seac Square

A short walk from your hotel, Tap Seac Square is a vibrant public space surrounded by colonial-style buildings.


#### Dr. Sun Yat Sen Memorial House

Explore the Dr. Sun Yat Sen Memorial House, a historic site dedicated to the revolutionary leader.


#### Museum of Sacred Art and Crypt

A five-minute walk from the Memorial House, this museum offers a glimpse into Macau's religious history.


#### Macao Grand Prix Museum

Car enthusiasts will enjoy the Macao Grand Prix Museum, showcasing the history of the famous race.


#### Grand Lisboa Building

Visit the iconic Grand Lisboa Building, an architectural marvel and a symbol of Macau's skyline.


#### Casino Grand Lisboa

Try your luck at Casino Grand Lisboa, one of the most famous casinos in Macau.


#### View of Lake Nam Van

Enjoy a serene view of Lake Nam Van, a perfect spot for a leisurely stroll.


#### Walls of St Paul Church

Explore the historic Walls of St Paul Church, a UNESCO World Heritage site.


#### Monte Fort

Visit Monte Fort, offering historical exhibits and panoramic views of the city.


#### Macao Museum

Discover Macau's rich history and culture at the Macao Museum, located within Monte Fort.


#### Senado Square

Stroll through Senado Square, a bustling public square with beautiful Portuguese-style buildings.


#### Macau Fisherman's Wharf

End your day with a visit to Macau Fisherman's Wharf, a waterfront complex with shopping, dining, and entertainment options.


#### Kun Iam Ecumenical Center

Visit the Kun Iam Ecumenical Center, a serene spot dedicated to the Goddess of Mercy.


#### Macau Tower Convention and Entertainment Center

Take in the breathtaking views from the Macau Tower, and if you're feeling adventurous, try the world's highest bungee jump.


#### A-Ma Temple

Explore the historic A-Ma Temple, one of Macau's oldest and most revered temples.


#### MGM Macau

End your day with a visit to MGM Macau, offering luxurious accommodations and entertainment options.


#### Lou Lim Ioc Garden

Relax at Lou Lim Ioc Garden, a peaceful retreat with traditional Chinese landscaping.


### Conclusion

Macau offers a perfect blend of luxury, culture, and history. This four-day itinerary covers the most iconic and must-visit places, ensuring you have an unforgettable experience. Whether you're exploring lavish casinos, historic sites, or cultural villages, Macau promises a unique and memorable journey. Happy travels!

Friday 16 February 2024

configuration-driven template in vue js

1. It's easier to read configuration


Reading code is complicated because you have to figure out what the logic is doing, but configuration is very straightforward to understand.


2. Less logic means less bugs


The config above is just a boring array with some objects. It's pretty simple, so it's unlikely that bugs would come from there.

3. Dynamic components are more flexible


Because we've made this menu component dynamically render out the different menu items, we gain tremendous flexibility.

 


Thursday 15 February 2024

JavaScript Sets New Helper Function Comming soon

const languages = new Set(["JavaScript","TypeScript","HTML","JavaScript"]);

languages.size;

// => 3


languages.add("JavaScript");

languages.add("CSS");

languages.size;

// => 4
You can add more elements to the Set with the add function.
Adding an element that is already in the Set doesn't do anything.


languages.delete("TypeScript");

languages.size;

// => 3


languages.has("JavaScript");

// => true

languages.has("TypeScript");

// => false


languages.forEach(element => console.log(element));

// "JavaScript"

// "HTML"

// "CSS"

Set.prototype.union(other)


A union of sets is a set that contains all the elements present in
either set.

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);

const allLanguages = frontEndLanguages.union(backEndLanguages);

// => Set {"JavaScript", "HTML", "CSS", "Python", "Java"}
In this example, all the languages from the first two sets are in
the third set.As with other methods that add elements to the Set,
duplicates are removed.



This is the equivalent of a SQL FULL OUTER JOIN between two tables.


Set.prototype.intersection(other)
An intersection is a set that contains all the elements that are
present within both sets.

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);

const frontAndBackEnd = frontEndLanguages.intersection(backEndLanguages);

// => Set {"JavaScript"}
"JavaScript" is the only element present in both the sets here.



An intersection is like an INNER JOIN.



Set.prototype.difference(other)
The difference between the set you are working with and another
set is all the elements present in the first set and not present
in the second set.

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);

const onlyFrontEnd = frontEndLanguages.difference(backEndLanguages);

// => Set {"HTML", "CSS"}

const onlyBackEnd = backEndLanguages.difference(frontEndLanguages);

// => Set {"Python", "Java"}
In finding the difference between sets, it matters which set you call
the function on and which is the argument. In the example above,
removing the back-end languages from the front-end languages results in
"JavaScript" being removed and returning "HTML" and "CSS" in the
resultant set. Whereas removing the front-end languages from the
back-end languages still results in "JavaScript" being removed,
and returns "Python" and "Java".


A difference is like performing a LEFT JOIN.



Set.prototype.symmetricDifference(other)

The symmetric difference between two sets is a set that contains all
the elements that are in one of the two sets, but not both.

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);

const onlyFrontEnd = frontEndLanguages.symmetricDifference(backEndLanguages);

// => Set {"HTML", "CSS", "Python", "Java"}

const onlyBackEnd = backEndLanguages.symmetricDifference(frontEndLanguages);

// => Set {"Python", "Java", "HTML", "CSS"}
In this case, the elements in the resultant sets are the same,
but note that the order is different.Set order is determined by the order
the elements are added to the set and the set on which the
function is performed will have its elements added first.



A symmetric difference is like a FULL OUTER JOIN excluding any elements
that are in both tables.




Tuesday 2 January 2024

New control flow for forLoop and empty in Angular 17

 


import {CommonModule} from '@angular/common';
import {Component} from '@angular/core';

@Component({
selector: 'app-root',
imports: [CommonModule],
template: `
Welcome to Angular-17!
<!-- new control flow for forLoop -->
<!-- new control flow to handle if, else if and else -->

@if(userInfo.isLoggedIn) {
<div>Logged-in</div>
} @else if(userInfo.isAdmin) {
<div>Admin</div>
} @else {
<div>Please Login</div>
}
@for (course of courses; track course) {
<div>{{course | json}}</div>
==================================
} @empty {
<div>No Courses found...</div>
}
`,
standalone: true,
})
export class AppComponent {

isLoading = false;
userInfo = {
isLoggedIn:true,
isAdmin:false
}
courses = [
{ id: 'r18', name: 'React + Redux'},
{ id: 'A17', name: 'Angular + NGRX'}
];

}

Wednesday 29 November 2023

How to Export HTML to Image in Angular Component


# How to Export HTML to Image in Angular Component

As a web developer, you may encounter scenarios where you need to export the content of an HTML element to an image. In this tutorial, we will explore how to achieve this using the `html2canvas` library in an Angular component.

## Step 1: Install the html2canvas Package

Firstly, install the `html2canvas` package using npm:

```bash
npm install html2canvas --save
```

## Step 2: Import Required Modules

In your Angular component file, import the necessary modules:

import { Component, OnInit, OnDestroy, ElementRef, ViewChild } from
"@angular/core";

import html2canvas from 'html2canvas';

## Step 3: Component Setup

Define the necessary elements in your component:

@ViewChild('screen') screen: ElementRef;
@ViewChild('canvas') canvas: ElementRef;
@ViewChild('downloadLink') downloadLink: ElementRef;

## Step 4: Implement Image Download Function

Add a function to download the HTML content as an image:

downloadImage(){
html2canvas(this.screen.nativeElement).then(canvas => {
this.canvas.nativeElement.src = canvas.toDataURL();
this.downloadLink.nativeElement.href = canvas.toDataURL('image/png');
this.downloadLink.nativeElement.download = 'full_page.png';
this.downloadLink.nativeElement.click();
});
}

## Step 5: HTML Setup

In your component's HTML file, set up the elements for exporting:

<div #screen>
<h1>Hello Test</h1>
</div>

<div id="download">
<img #canvas>
<a #downloadLink></a>
</div>

## Step 6: Invoking the Function

Call the `downloadImage` function from your component when you want to trigger the export.

Now you have a complete setup to export HTML content as an image in your Angular component using `html2canvas`. Feel free to customize the code according to your specific requirements.

Happy coding!


Tuesday 17 October 2023

get multiple group by sum in javascript


 



let jsonData = {
"status": true,
"data": [
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Global",
"esg_audited": "non-audited",
"size": "large",
"invoice_count": 1
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Global",
"esg_audited": "audited",
"size": "large",
"invoice_count": 1
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Global",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 5
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Global",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 5
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Global",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 1
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Global",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 7
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "non-audited",
"size": "large",
"invoice_count": 7
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "non-audited",
"size": "sme",
"invoice_count": 23
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "large",
"invoice_count": 3
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 13
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 1
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 5
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 2
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 4
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 1
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 1
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 1
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 1
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 4
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 1
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 1
},
{
"year": 2021,
"quarter": 4,
"month": 12,
"mthkey": 202112,
"supplier": "root",
"demography": "Local",
"esg_audited": "audited",
"size": "sme",
"invoice_count": 2
}
]
}
----------------------------------
Function
----------------------------------
groupByMultis(data, keys,count_property_name) {
const counts = {};
data.forEach(item => {
let currentLevel = counts;
keys.forEach((key, index) => {
const value = item[key];
if (!currentLevel[value]) {
currentLevel[value] = { count: 0 };
}
currentLevel[value].count += item[count_property_name];
let val = parseFloat(parseFloat(currentLevel[value].count).toFixed(2));
currentLevel[value].count = val;
currentLevel = currentLevel[value];
});
});
return counts;
}
----------------------------------
Use
----------------------------------
let groupByMultisResult = this.groupByMultis(jsonData.data,
['esg_audited','demography','size'],'invoice_count');
----------------------------------
Result
----------------------------------
{
"non-audited": {
"count": 101,
"Global": {
"count": 36,
"large": {
"count": 2
},
"sme": {
"count": 34
}
},
"Local": {
"count": 65,
"large": {
"count": 14
},
"sme": {
"count": 51
}
}
},
"audited": {
"count": 147,
"Global": {
"count": 36,
"large": {
"count": 2
},
"sme": {
"count": 34
}
},
"Local": {
"count": 111,
"large": {
"count": 28
},
"sme": {
"count": 83
}
}
}
}



loopThroughObjRecurs (obj, count,propExec) {
for (var k in obj) {
if (typeof obj[k] === 'object' && obj[k] !== null) {
let currentCount = obj[k].count;
let percentage:any = (currentCount*100/count);
let val = parseFloat(parseFloat(percentage).toFixed(2));
obj[k]['percentage'] = val;
this.loopThroughObjRecurs(obj[k], obj[k].count,propExec)
} else if (obj.hasOwnProperty(k)) {
propExec(k, obj[k])
}
}
}

let rootCount = _.sumBy(jsonData.data,'invoice_count');
let withPercentage = loopThroughObjRecurs(groupByMultisResult,rootCount,
function(k, prop) {
//console.log(k + ': ' + prop);
});