1656759600
It generate a self contained and gziped file index.html.gz
。Use for small space drive and embedded device. Alike ESP32 OTA mode just less than 170KB space!
npx degit MillerRen/vite-singlefile-gzip my-project
cd my-project
npm install
npm run dev
npm run build
Author: MillerRen
Source code: https://github.com/MillerRen/vite-singlefile-gzip
License:
1656759600
It generate a self contained and gziped file index.html.gz
。Use for small space drive and embedded device. Alike ESP32 OTA mode just less than 170KB space!
npx degit MillerRen/vite-singlefile-gzip my-project
cd my-project
npm install
npm run dev
npm run build
Author: MillerRen
Source code: https://github.com/MillerRen/vite-singlefile-gzip
License:
1605576444
If you are coming from the background of working with angularjs, it was quite straight forward to access and manipulate the DOM there. You had access to the DOM node through element
injected in the link
function of the directive.
function link(scope, element, attrs) {
}
Or through angular.element
which was an AngularJS’s built in subset of jQuery. But this approach had its drawbacks. It made your code tightly coupled with Browser’s API.
The new Angular (2 onwards) works on multiple platforms: mobile, web workers etc. So, they have introduced a number of APIs to work as an abstraction layer between your code and platform APIs. These APIs come in the form of different reference types likeElementRef
, TemplateRef
, ViewRef
, ComponentRef
and ViewContainerRef
.
In this blog, we will see some examples of how these reference types can be used to manipulate DOM in angular. But before that let’s look at the ways to access these reference types within a Component/Directive.
DOM Queries
Angular has provided two ways to query/access various reference types within a Component/Directive. These are
These are decorators which can be used within a Component/Directive as @ViewChild
(returns a single reference) or @ViewChildren
(returns a list of references in the form of a QueryList
). These will assign the values of reference types from template to the component fields they are applied to. The basic usage is as follow:
@ViewChild(selector, {read: ReferenceType}) fieldName;
A selector can be a string representing a template reference variable, or a Component/Directive class, or a TemplateRef or a provider defined in the child component tree.
@ViewChild("myElem") template: ElementRef;
The second parameter is optional and is only required to query some reference types which can’t be inferred easily by Angular like ViewContainerRef
.
@ViewChild("myContainer", {read: ViewContainerRef}) container: ViewContainerRef;
The usage is pretty much similar to that of ViewChild/ViewChildren. The only difference is that it queries within the <ng-content>
projected elements of the component while the @ViewChild
queries within the template of the component. This will be explained better in the examples of upcoming sections.
DOM access via ElementRef
ElementRef
is a very basic abstraction layer on a DOM element in Angular. It’s an angular wrapper around the native element.
You can get hold of ElementRef in a Component or Directive in following ways:
Host element of a Component or Directive can be accessed via direct DI in the constructor.
@Component({
selector: 'app-test',
template: '<div>I am a test component</div>'
})
export class TestComponent implements OnInit {
constructor(private element: ElementRef) { }
ngOnInit() {
console.log(this.element.nativeElement);
}
}
/*
* Output:
* <app-test>
* <div>I am a test component</div>
* </app-test>
* */
@Component({
selector: 'app-test',
template: `
<div #child1>First Child</div>
<div>Second Child</div>
`
})
export class TestComponent implements OnInit {
@ViewChild("child1") firstChild: ElementRef;
constructor() { }
ngOnInit() {
console.log(this.firstChild.nativeElement);
}
}
/*
* Output: <div>First Child</div>
* */
Works in a similar manner as that of @ViewChild
, but for <ng-content>
projected elements.
// Child Component
@Component({
selector: "component-a",
template: `<ng-content></ng-content>`
})
export class ComponentA {
@ContentChild("contentChild") contentChild: ElementRef;
ngOnInit() {
console.log(this.contentChild.nativeElement);
}
}
// Parent Component
@Component({
selector: 'app-test',
template: `
<component-a>
<div #contentChild>Content Child 1</div>
<div>Content Child 2</div>
</component-a>
`
})
export class TestComponent implements OnInit {}
/*
* Output: <div>Content Child 1</div>
* */
It looks pretty straight forward that you can easily access a DOM element via ElementRef
and then manipulate the DOM by accessing the nativeElement
. Something like this:
@Component({
selector: 'app-test-component',
template: `
<div class="header">I am a header</div>
<div class="body" #body>
</div>
<div class="footer">I am a footer</div>
`
})
export class TestComponent implements AfterContentInit {
@ViewChild("body") bodyElem: ElementRef;
ngAfterContentInit(): void {
this.bodyElem.nativeElement.innerHTML = `<div>Hi, I am child added by directly calling the native APIs.</div>`;
}
}
However, the direct usage of ElementRef is discouraged by Angular Team because it directly provides the access to DOM which can make your application vulnerable to XSS attacks. It also creates tight coupling between your application and rendering layers which makes is difficult to run an app on multiple platforms.
Everything is a ‘View’ in Angular
A view is the smallest building block of an angular app’s UI. Every component has its own view. You can consider it as a group of elements which can be created and destroyed together.
A view can be classified into two types:
Displaying a view in UI can be broken down into two steps:
Embedded Views
Embedded views are created from templates defined using <ng-template>
element.
First a template needs to be accessed within a component as TemplateRef
using @ViewChild
and template reference variable. Then, an embedded view can be created from a TemplateRef
by passing a data-binding context.
const viewRef = this.template.createEmbeddedView({
name: "View 1"
});
This context is being consumed by the template in<ng-template>
.
<ng-template #template let-viewName="name">
<div>Hi, My name is {{viewName}}. I am a view created from a template</div>
</ng-template>
You can also use the $implicit
property in the context if you have only a single property to bind.
const viewRef = this.template.createEmbeddedView({
$implicit: "View 1"
});
In this case, you can skip assigning values to template variables.
<ng-template #template let-viewName>
<div>Hi, My name is {{viewName}}. I am a view created from a template</div>
</ng-template>
Till now, we have created only an instance of ViewRef
. This view is still not visible in the UI. In order to see it in the UI, we need a placeholder (a view container) to render it. This placeholder is being provided by ViewContainerRef
.
Any element can serve as a view container, however <ng-container>
is a better candidate as it is rendered as a comment and doesn’t leave any redundant element in the html DOM.
@Component({
selector: 'app-test-component',
template: `
<div class="header">I am a header</div>
<div class="body">
<ng-container #container></ng-container>
</div>
<div class="footer">I am a footer</div>
<ng-template #template let-viewName="name">
<div>Hi, My name is {{viewName}}. I am a view created from a template</div>
</ng-template>
`,
})
export class TestComponent implements AfterContentInit {
@ViewChild("template") template: TemplateRef;
@ViewChild("container", {read: ViewContainerRef}) container: ViewContainerRef;
constructor() { }
ngAfterContentInit(): void {
const viewRef = this.template.createEmbeddedView({
name: "View 1"
});
this.container.insert(viewRef);
}
}
Both <ng-container>
and <ng-template>
elements will be rendered as comments leaving the html DOM neat and clean.
The above 2 steps process of creating a view and adding it into a container can further be reduced by using the createEmbeddedView
method available in the ViewContainerRef
itself.
this.container.createEmbeddedView(this.template, {
name: "View 1"
});
This can be further simplified by moving the whole view creation logic from component class to the template using ngTemplateOutlet
and ngTemplateOutletContext
.
@Component({
selector: 'app-test-component',
template: `
<div class="header">I am a header</div>
<div class="body">
<ng-container [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{name: 'View 1'}"></ng-container>
</div>
<div class="footer">I am a footer</div>
<ng-template #template let-viewName="name">
<div>Hi, My name is {{viewName}}. I am a view created from a template</div>
</ng-template>
`
})
export class TestComponent {}
Host Views
Host Views are quite similar to Embedded View. The only difference is that the Host Views are created from components instead of templates.
In order to create a host view, first you need to create a ComponentFactory
of the component you want to render using ComponentFactoryResolver
.
constructor(
private componentFactoryResolver: ComponentFactoryResolver
) {
this.someComponentFactory = this.componentFactoryResolver.resolveComponentFactory(SomeComponent);
}
Then, a dynamic instance of the component is created by passing an Injector
instance to the factory. Every component should be bound to an instance of Injector
. You can use the injector of the parent component for the dynamically created components.
const componentRef = this.someComponentFactory.create(this.injector);
const viewRef = componentRef.hostView;
Rendering a host view is almost similar to rendering an embedded view. You can directly insert it into a view container.
@Component({
selector: 'app-test-component',
template: `
<div class="header">I am a header</div>
<div class="body">
<ng-container #container></ng-container>
</div>
<div class="footer">I am a footer</div>
`,
})
export class TestComponentComponent implements AfterContentInit {
@ViewChild("container", {read: ViewContainerRef}) container: ViewContainerRef;
private someComponentFactory: ComponentFactory<SomeComponent>;
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector
) {
this.someComponentFactory = this.componentFactoryResolver.resolveComponentFactory(SomeComponent);
}
ngAfterContentInit(): void {
const componentRef = this.someComponentFactory.create(this.injector);
const viewRef = componentRef.hostView;
this.container.insert(viewRef);
}
}
Or by directly calling the createComponent
method of ViewContainerRef
and passing the component factory instance.
this.container.createComponent(this.someComponentFactory);
Now, similar to embedded view, we can also shift the whole logic of host view creation in template itself using ngComponentOutlet
.
@Component({
selector: 'app-test-component',
template: `
<div class="header">I am a header</div>
<div class="body">
<ng-container [ngComponentOutlet]="comp"></ng-container>
</div>
<div class="footer">I am a footer</div>
`
})
export class TestComponent {
comp = SomeComponent;
}
Don’t forget to store the reference of the component class in parent component’s field. The template has access only to the fields of the components.
Here we come to an end. Let’s conclude what we have understood till now.
ElementRef
, TemplateRef
, ViewRef
, ComponentRef
and ViewContainerRef
.@ViewChild
and @ContentChild
.ElementRef
. However, manipulating this element directly is discouraged because of security reasons.So, that’s it for today about understanding DOM manipulation in Angular.
Originally published by medium
1656727200
Vite starter template to scaffold a new Mithril project.
This is an unopinionated template; aside from Mithril and Vite, the rest of your project's tools are entirely up to you.
Pull the template files with degit and install dependencies.
npx degit ArthurClemens/mithril-vite-starter my-project
cd my-project
npm install
npm run dev
- Starts the development server at port 3000npm run build
- Builds the applicationnpm run preview
- Serves the build files locally at port 5000Uncomment the esbuild
configuration in vite.config.js
.
Example App.jsx
:
import m from "mithril";
import "./App.css";
export const App = () => {
// Local state ...
return {
view: () => {
return (
<>
<h1>My Mithril App</h1>
</>
)
},
};
};
Author: ArthurClemens
Source code: https://github.com/ArthurClemens/mithril-vite-starter
License:
1656568800
Opinionated Vite starter template.
An starter template for Vite React 18 projects including a bunch of useful tools and libraries enforcing best practices and autofix on save.
For styling it comes with SASS, Emotion, and TailwindCSS ready to use. Choose your favorite CSS framework and get started. It also includes the @namics/stylelint-bem plugin for BEM style validation.
To get a local copy up and running follow these simple example steps.
node
: >=16.13.0
npm
or pnpm
or yarn
I advice to use pnpm
for managing dependencies. It's faster and more reliable than npm
. To install pnpm just run:
corepack enable
corepack prepare pnpm@7.0.0-rc.3 --activate
After that the syntax is the same as npm
e.g. npm install
becomes pnpm install
.
npm install
or pnpm install
or yarn
npm run dev
or pnpm run dev
or yarn run dev
and open the browser at http://localhost:3000
npm run build
or pnpm run build
or yarn run build
After creating the production build, run:
npm run preview
or yarn run preview
npm run serve
or pnpm run serve
or yarn run serve
and open the browser at http://localhost:4173
GitHub | @fabgrel10 |
@fabgrel10 | |
@fabgrel10 |
You can give a ⭐️ if you like this project!
The ideas and inspiration from this project are coming from the following:
Author: fabgrel10
Source code: https://github.com/fabgrel10/vite-react-starter
License:
1656756000
⚡️ A minimal React Vite starter template.
npx degit 0x219/template-vite-react myapp
cd myapp
npm
and pnpm
should be installed.git
should be installed (recommended v2.4.11 or higher)pnpm dev
Runs the app in development mode. Open https://localhost:3000 to view it in the browser.
The page will automatically reload if you make changes to the code. You will see the build errors and lint warnings in the console.
pnpm build
Builds the app for production to the dist
folder. It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed.
Author: 0x219
Source code: https://github.com/0x219/template-vite-react
License: