Smart.Grid as a standalone Angular component
This topic will show you how to use Smart.Grid and any other of our components in a combination of the new Angular's feature: standalone components. This feature was a preview in Angular 14 and now in Angular 15, it was introduced as a stable API.
What are standalone components?
The long-awaited feature: standalone components, allow the developer to create a component without declaring it in a NgModule. You can directly import the newly created component into another one. Standalone components can manage their template dependencies alone without NgModule. That reduces the need for NgModule and can make it optional. The goal is to shift the focus from NgModules to Components. A standalone component is marked as standalone with the property standalone: true The dependencies are directly specified in an imports array
Setup Angular Environment
To create new Angular project we need Angular cli:
npm install -g @angular/cli
the -g flag is for global. Once you install it you can use it everywhere, not only in this project.
Create a new project this way:
ng new smart-app
We do not need routing and we will use CSS, so press enter two times
Next navigate to smart-app
cd smart-app
-
Delete src/app.component.spec.ts
Delete src/app.module.ts
-
Remove Everything from src/app.component.html
-
Convert src/app/app.component.ts to standalone:
@Component({ selector: 'app-root', standalone: true, templateUrl: './app.component.html', styleUrls: ['./app.component.css'], imports: [] })
-
Bootstrap the AppComoponent in the main.ts file:
// in the main.ts file import { bootstrapApplication } from '@angular/platform-browser'; import { AppComponent } from './app/app.component'; bootstrapApplication(AppComponent);
Setup Smart UI
Smart UI for Angular is distributed as smart-webcomponents-angular NPM package
-
Open the terminal and install the package:
ng add smart-webcomponents-angular
The command executes the following actions:
- Adds the smart-webcomponents-angular package as a dependency.
- Imports the Modules in the current application module.
- Registers the default Smart UI theme in the angular.json file.
- Adds all required peer dependencies to package.json
- Triggers npm install to install the theme and all peer packages that are added.
Import the GridModule
Standalone components can use existing NgModules by directly importing them in the imports array.
To use Smart.Grid we should import our GridModule in our application and since we are using a standalone component we will import it into the imports array:
import the GridModule directly in app.component.ts
import { GridModule } from 'smart-webcomponents-angular/grid'; @Component({ selector: 'app-root', standalone: true, templateUrl: './app.component.html', styleUrls: ['./app.component.css'], imports: [GridModule] })
Initialize Smart.Grid
We did everything required to use Smart.Grid and it is time to create it:
Open app.component.html and use smart-grid component as shown:
<smart-grid #grid id="grid" [dataSource]="dataSource" [columns]="columns"></smart-grid>
Now you must initialize the properties for the grid
Open app.component.ts and paste the following inside the component's class:
export class AppComponent { title = 'smart-app'; @ViewChild('grid', { read: GridComponent, static: false }) grid!: GridComponent; dataSource = new Smart.DataAdapter({ dataSource: [], dataFields: [ 'id: number', 'firstName: string', 'lastName: string', 'productName: string', 'available: bool', 'quantity: number', 'price: number', 'total: number' ] }) columns = [ { label: 'First Name', dataField: 'firstName' }, { label: 'Last Name', dataField: 'lastName' }, { label: 'Product', dataField: 'productName' }, { label: 'Available', dataField: 'available', template: 'checkBox' }, { label: 'Quantity', dataField: 'quantity' }, { label: 'Unit Price', dataField: 'price', cellsFormat: 'c2' } ] }
Injecting data service
You may have seen that the grid is empty that is happening because in the dataSource we passed an empty array. Now we will create a data service for our grid. This will show you how to use dependency injection with the standalone approach
- Open the terminal and run
ng g service data
- Delete data.service.spec.ts
-
Open data.service.ts and replace the
@Injectable({ providedIn: 'root' })
with@Injectable()
-
Add the following interface above the
@Injectable()
interface IRowGenerateData { id: number; reportsTo: number | null; available: boolean | null; firstName: string; lastName: string; name: string; productName: string; quantity: string | number; total: string | number; price: string | number; date: Date; leaf: boolean; }
-
Add this method inside the class:
export class DataService { constructor() {} GetData(rowscount?: number, last?: number, hasNullValues?: boolean): IRowGenerateData[] { const data: IRowGenerateData[] = new Array(); if (rowscount === undefined) { rowscount = 100; } let startIndex = 0; if (last) { startIndex = rowscount; rowscount = last - rowscount; } const firstNames = [ 'Andrew', 'Nancy', 'Shelley', 'Regina', 'Yoshi', 'Antoni', 'Mayumi', 'Ian', 'Peter', 'Lars', 'Petra', 'Martin', 'Sven', 'Elio', 'Beate', 'Cheryl', 'Michael', 'Guylene' ]; const lastNames = [ 'Fuller', 'Davolio', 'Burke', 'Murphy', 'Nagase', 'Saavedra', 'Ohno', 'Devling', 'Wilson', 'Peterson', 'Winkler', 'Bein', 'Petersen', 'Rossi', 'Vileid', 'Saylor', 'Bjorn', 'Nodier' ]; const productNames = [ 'Black Tea', 'Green Tea', 'Caffe Espresso', 'Doubleshot Espresso', 'Caffe Latte', 'White Chocolate Mocha', 'Caramel Latte', 'Caffe Americano', 'Cappuccino', 'Espresso Truffle', 'Espresso con Panna', 'Peppermint Mocha Twist' ]; const priceValues = [ '2.25', '1.5', '3.0', '3.3', '4.5', '3.6', '3.8', '2.5', '5.0', '1.75', '3.25', '4.0' ]; for (let i = 0; i < rowscount; i++) { const row = {} as IRowGenerateData; const productindex = Math.floor(Math.random() * productNames.length); const price = parseFloat(priceValues[productindex]); const quantity = 1 + Math.round(Math.random() * 10); row.id = startIndex + i; row.reportsTo = Math.floor(Math.random() * firstNames.length); if (i % Math.floor(Math.random() * firstNames.length) === 0) { row.reportsTo = null; } row.available = productindex % 2 === 0; if (hasNullValues === true) { if (productindex % 2 !== 0) { const random = Math.floor(Math.random() * rowscount); row.available = i % random === 0 ? null : false; } } row.firstName = firstNames[Math.floor(Math.random() * firstNames.length)]; row.lastName = lastNames[Math.floor(Math.random() * lastNames.length)]; row.name = row.firstName + ' ' + row.lastName; row.productName = productNames[productindex]; row.price = price; row.quantity = quantity; row.total = price * quantity; const date = new Date(); date.setFullYear(2016, Math.floor(Math.random() * 11), Math.floor(Math.random() * 27)); date.setHours(0, 0, 0, 0); row.date = date; data[i] = row; } return data; } }
- The next step is to provide this service in our application, so open the main.ts file and add pass options to the bootstrapApplication method:
bootstrapApplication(AppComponent, { providers: [ DataService ] });
This is the way of using dependency injection with standalone components.
Filling Smart.Grid with data
Now since we have an injectable service, it is time to inject it in our AppComponent and use the GetData method to fill the Smart.Grid
Open app.component.ts and add the following constructor that will inject our service:
constructor(private dataService: DataService) {}
Now use the GetData function to pass records to the grid
dataSource = new Smart.DataAdapter({ dataSource: this.dataService.GetData(100), dataFields: [ 'id: number', 'firstName: string', 'lastName: string', 'productName: string', 'available: bool', 'quantity: number', 'price: number', 'total: number' ] })
Result
Our Smart.Grid is ready and filled with data, this should be the result of the help topic: