1677147000
NGX MASK is the best directive to solve masking input with needed pattern.
$ npm install --save ngx-mask
Import ngx-mask directive, pipe and provide NgxMask providers with provideNgxMask
function.
bootstrapApplication(AppComponent, {
providers: [
(...)
provideEnvironmentNgxMask(),
(...)
],
}).catch((err) => console.error(err));
import { IConfig } from 'ngx-mask'
const maskConfig: Partial<IConfig> = {
validation: false,
};
bootstrapApplication(AppComponent, {
providers: [
(...)
provideEnvironmentNgxMask(maskConfig),
(...)
],
}).catch((err) => console.error(err));
const maskConfigFunction: () => Partial<IConfig> = () => {
return {
validation: false,
};
};
bootstrapApplication(AppComponent, {
providers: [
(...)
provideEnvironmentNgxMask(maskConfigFunction),
(...)
],
}).catch((err) => console.error(err));
@Component({
selector: 'my-feature',
templateUrl: './my-feature.component.html',
styleUrls: ['./my-feature.component.css'],
standalone: true,
imports: [NgxMaskDirective, (...)],
providers: [
(...)
provideNgxMask(),
(...)
],
})
export class MyFeatureComponent {}
Then, import directive, pipe to needed standalone component and just define masks in inputs.
@NgModule({
imports: [
NgxMaskDirective, NgxMaskPipe
],
providers: [provideNgxMask()]
})
For version ngx-mask < 15.0.0 Import ngx-mask module in Angular app.
import { NgxMaskModule, IConfig } from 'ngx-mask'
export const options: Partial<null|IConfig> | (() => Partial<IConfig>) = null;
@NgModule({
imports: [
NgxMaskModule.forRoot(),
],
})
import { NgxMaskModule, IConfig } from 'ngx-mask'
const maskConfig: Partial<IConfig> = {
validation: false,
};
@NgModule({
imports: [
NgxMaskModule.forRoot(maskConfig),
],
})
Or using a function to get the config:
const maskConfigFunction: () => Partial<IConfig> = () => {
return {
validation: false,
};
};
@NgModule({
imports: [
NgxMaskModule.forRoot(maskConfigFunction),
],
})
Then, just define masks in inputs.
<input type="text" mask="<here goes your mask>" />
or
<input type="text" [mask]="<here goes a reference to your component's mask property>" />
Also, you can use mask pipe.
<span>{{phone | mask: '(000) 000-0000'}}</span>
For separator you can add thousandSeparator
<span>{{value | mask: 'separator':','}}</span>
mask | example |
---|---|
9999-99-99 | 2017-04-15 |
0*.00 | 2017.22 |
000.000.000-99 | 048.457.987-98 |
AAAA | 0F6g |
SSSS | asDF |
UUUU | ASDF |
LLLL | asdf |
You can define your custom options for all directives (as object in the mask module) or for each (as attributes for directive). If you override this parameter, you have to provide all the special characters (default one are not included).
We have next default characters:
character |
---|
- |
/ |
( |
) |
. |
: |
space |
+ |
, |
@ |
[ |
] |
" |
' |
<input type="text" [specialCharacters]="[ '[' ,']' , '\\' ]" mask="[00]\[000]" />
Then
Input value: 789-874.98
Masked value: [78]\[987]
patterns ({ [character: string]: { pattern: RegExp, optional?: boolean})
We have next default patterns:
code | meaning |
---|---|
0 | digits (like 0 to 9 numbers) |
9 | digits (like 0 to 9 numbers), but optional |
A | letters (uppercase or lowercase) and digits |
S | only letters (uppercase or lowercase) |
U | only letters uppercase |
L | only letters lowercase |
Usage
<input type="text" [patterns]="customPatterns" mask="(000-000)" />
and in your component
public customPatterns = { '0': { pattern: new RegExp('\[a-zA-Z\]')} };
Then
Input value: 789HelloWorld
Masked value: (Hel-loW)
You can define custom pattern and specify symbol to be rendered in input field.
pattern = {
B: {
pattern: new RegExp('\\d'),
symbol: 'X',
},
};
You can add prefix to you masked value
<input type="text" prefix="+7" mask="(000) 000 00 00" />
You can add suffix to you masked value
<input type="text" suffix="$" mask="0000" />
You can choose if mask will drop special character in the model, or not, default value is true
.
<input type="text" [dropSpecialCharacters]="false" mask="000-000.00" />
Then
Input value: 789-874.98
Model value: 789-874.98
You can choose if mask is shown while typing, or not, default value is false
.
<input mask="(000) 000-0000" prefix="+7" [showMaskTyped]="true" />
You can choose if mask will allow the use of negative numbers. The default value is false
.
<input type="text" [allowNegativeNumbers]="true" mask="separator.2" />
Then
Input value: -10,000.45
Model value: -10000.45
If the showMaskTyped
parameter is enabled, this setting customizes the character used as placeholder. Default value is _
.
<input mask="(000) 000-0000" prefix="+7" [showMaskTyped]="true" placeHolderCharacter="*" />
You can choose clear the input if the input value not match the mask, default value is false
.
You can pass array of expression and custom Pattern to pipe.
<span>{{phone | mask: customMask}}</span>
and in your component
customMask: [string, pattern];
pattern = {
P: {
pattern: new RegExp('\\d'),
},
};
this.customMask = ['PPP-PPP', this.pattern];
You can pass into mask pattern with brackets.
<input type="text" mask="A{4}" />
You can divide your input by thousands, by default will seperate with a space.
<input type="text" mask="separator" />
For separate input with dots.
<input type="text" mask="separator" thousandSeparator="." />
For using decimals enter .
and how many decimals to the end of your input to separator
mask.
<input type="text" mask="separator.2" />
Input value: 1234.56
Masked value: 1 234.56
Input value: 1234,56
Masked value: 1.234,56
Input value: 1234.56
Masked value: 1,234.56
<input type="text" mask="separator.2" thousandSeparator="." />
<input type="text" mask="separator.2" thousandSeparator="," />
<input type="text" mask="separator.0" thousandSeparator="." />
<input type="text" mask="separator.0" thousandSeparator="," />
For limiting decimal precision add .
and the precision you want to limit too on the input. 2 is useful for currency. 0 will prevent decimals completely.
Input value: 1234,56
Masked value: 1.234,56
Input value: 1234.56
Masked value: 1,234.56
Input value: 1234,56
Masked value: 1.234
Input value: 1234.56
Masked value: 1,234
<input type="text" mask="separator.2" separatorLimit="1000" />
For limiting the number of digits before the decimal point you can set separatorLimit
value to 10, 100, 1000 etc.
Input value: 12345678,56
Masked value: 1.234,56
You can validate your input as 24 hour format.
<input type="text" mask="Hh:m0:s0" />
You can validate your date.
<input type="text" mask="d0/M0/0000" />
If the leadZeroDateTime
parameter is true
, skipped symbols of date or time will be replaced by 0
. Default value is false
.
<input type="text" mask="d0/M0/0000" [leadZeroDateTime]="true" />
Input value: 422020
Masked value: 04/02/2020
<input type="text" mask="Hh:m0:s0" [leadZeroDateTime]="true" />
Input value: 777
Masked value: 07:07:07
You can validate your input for percents.
<input type="text" mask="percent" suffix="%" />
You can validate your formControl
, default value is true
.
<input type="text" mask="00 00" [validation]="true" />
You can hide symbols in input field and get the actual value in formcontrol
.
<input placeholder="Secure input" [hiddenInput]="true" mask="XXX/X0/0000" />
<input mask="IP" />
<input mask="CPF_CNPJ" />
You can pass into mask pattern with ||
.
<input mask="000.000.000-00||00.000.000/0000-00" />
<input mask="(00) 0000-0000||(00) 0 0000-0000" />
<input mask="0000" (maskFilled)="maskFilled()" />
You can also try our NGX LOADER INDICATOR check. You can also try our NGX COPYPASTE check.
Author: JsDaddy
Source Code: https://github.com/JsDaddy/ngx-mask
License: MIT license
1674094800
A simplified Jira clone built with Angular, Akita and ng-zorro
There have been a handful of cool Jira-cloned apps written in React
/VueJS
, which makes me wonder Why not Angular? And here you go.
This is not only a simplified Jira clone built with Angular, but also an example of a modern, real-world Angular codebase.
Thank you for your support! -> https://jira.trungk18.com/project/issue/2020
Check out the live demo -> https://jira.trungk18.com
Storybook helps you build UI components in isolation from your app's business logic, data, and context. That makes it easy to develop hard-to-reach states. Save these UI states as stories to revisit during development, testing, or QA.
This is the collection of components that I wrote for jira.trungk18.com, includes:
Check out the storybook demo -> https://jira-storybook.trungk18.com/
I have been working with Angular for about four years. I built cool stuff at Zyllem but almost all of them are internal apps which is difficult to show.
This is a showcase application I've built in my spare time to experiment the new library that I wanted to try before: Akita
, TailwindCSS
, ng-zorro
.
There are many Angular examples on the web but most of them are way too simple. I like to think that this codebase contains enough complexity to offer valuable insights to Angular developers of all skill levels while still being relatively easy to understand.
This piece of work is also part of our technical series angular-vietnam/100-days-of-angular which aims at enabling everyone, after 100 days of learning Angular with us, to self-build their application with the similar scale. Our desire is to advocate and grow the Angular developer community in Vietnam.
tooltip
, modal
, select
, icon
and more.As requested by @eric_cart, I draw a simple high-level design for the application.
I have an AppModule that will import:
BrowserModule
and any module that need to run forRoot
.AuthModule
that need to available on the whole platform.LoginModule
when I open the URL at /login
and ProjectModule
when the URL is /project
. Inside each modules, I could import whatever modules that are required. Such as I need the JiraControlModule
for some custom UI components for the ProjectModule
As I am using Akita state management, I follow the Akita documentation for the data flow. I found it is simple to understand comparing with ngrx terms (reducer
, selector
, effect
)
I set up a project state with initial data. The main heavy lifting part I think is the project service, it contains all the interacting with project store. Such as after fetching the project successfully, I update the store immediately inside the service itself. The last lego block was to expose the data through project query. Any components can start to inject project query and consume data from there.
If you are using ngrx, you have to dispatch an action when you started fetching the project, and then there is an effect somewhere that was detached from your context need to handle the action, send a request to the API server. And finally, the effect will tell whether the data was successfully fetched or not. There is nothing wrong with ngrx approach, it is just too much concept and layer that you need to understand. To be honest, I used to afraid of integrating ngrx in my project because of the unnecessary complexity it would bring.
I set the tentative deadline for motivating myself to finish the work on time. Otherwise, It will take forever to complete :)
June 13 - 27, 2020
Noted: All of your interactions with data such as leave a comment or change the issue detail will not be saved to the persistent database. Currently, the application will serve a fixed structure of data every time you open the app. It means if you reload the browser, all of your changes will be gone.
Phase 2 will bring you a proper API where you can log in and save your work.
While working with this application, I have the opportunity to revisit some of the interesting topics:
I will take two weeks break to:
TBD
View the current work in progress branch
When I look at the application, it is huge. When the task is huge, you usually don't know where and how to start working with them. I started to break the big task into a simple to-do list on notion. Once I know what needs to be done, what I need is to follow the plan. That's my approach.
I learned a lot of stuff. I know you might also have a curiosity about the process of building the same scale app as well. That's why I am writing a tutorial series on how I built Angular Jira clone from scratch. I hope you guys will learn something from that too :)
I will try to be as detailed as possible. Hopefully through the tutorial, you will get the idea and will start working on your own application soon. Please bear with me.
Its series will also be published in Vietnamese as part of our angular-vietnam/100-days-of-angular.
It is a side project that I only spent time outside of the office hours to work on. One day, my team and I were fire fighting on PROD until 11 PM. After taking a shower, I continue with Angular Jira clone for another two hours...
According to waka time report, I have spent about 45 hours working on this project. Which is equivalent to watch the whole Stranger Things series twice.
I really enjoyed working on this project. The interactive kanban board took me sometimes, it is challenging but exciting at the same time.
There are missing features from the live demo which should exist in a real product. All of them will be finished on Phase 2:
I am currently sending the same email and a random password to the server without any check to get the current user back. Phase 2 will also bring a proper authentication system.
Not all components have properly defined aria attributes, visual focus indicators, etc.
git clone https://github.com/trungk18/jira-clone-angular.git
cd jira-clone-angular
npm start
for angular web applicationhttp://localhost:4200/
I skipped writing test for this project. I might do it for the proper backend GraphQL API.
It was being tested on IE 11, Chrome and Firefox. For Safari, there are some minor alignment issues.
If you have any ideas, just open an issue and tell me what you think.
If you'd like to contribute, please fork the repository and make changes as you'd like. Pull requests are warmly welcome.
Inspired by oldboyxx/jira_clone and Datlyfe/jira_clone.
I reused part of the HTML and CSS code from these projects.
Phase two will not be completed as planned. Both Chau Tran and I was too busy with some other commitments. View our working in progress Graph QL branch.
You can check the storybook collection of components I wrote for Jira Clone ➡ jira-storybook.trungk18.com 📕
Thanks for your continuous support. Stay tuned! 💪
Author: trungk18
Source Code: https://github.com/trungk18/jira-clone-angular
License: MIT license
1672512780
This project has two faces:
schematics
(used with the ng add
command) which can be applied to existing Angular projects. All schematics
comes from the boilerplate mentioned above. The main goal is to make those schematics interchangeably (developer can apply them in any order)!If you want to sharpen your skills in Angular Universal or you won't find what you're looking for in this project; check out the Guide to Angular Universal written by me for Newline.co!
npm install -g @ng-toolkit/init
ng new --collection @ng-toolkit/init myApp [--provider --firebaseProject --gaTrackingCode --firebug]
Add update mechanism and server-side rendering fixes to your PWA
ng add @ng-toolkit/pwa [--serverModule]
Make your app deployable on serverless environment (FaaS)
ng add @ng-toolkit/serverless [--provider --firebaseProject]
Add server-side rendering and improve SEO of your app
ng add @ng-toolkit/universal
Add firebug-lite to your Angular app
ng add @ng-toolkit/firebug
Feel free to create issue with your feature request
You can support development of this project via:
If you want, you can be listed on the List of donors on the demo page.
Author: maciejtreder
Source Code: https://github.com/maciejtreder/ng-toolkit
License: MIT license
1671660840
ng-template
, ng-container
, and ngTemplateOutlet
provide the ability to reuse content inside an Angular component. Understanding what’s going on and how to use these methods allows a developer to build what they want without needing to duplicate parts of the template.
Have you ever needed to use *ngIf
in your template, and if the expression evaluates to false use a backup template? On top of that, maybe both situations (if the expression is true or false) require the same layout inside of the element that has the *ngIf
directive on it.
I recently had came across this situation. We had some data that was being output in a list either had a link that stayed internal to the app or opened a link in a new tab external to the application. The content inside the links, however, always had the same layout. I didn’t want to duplicate the inner content, and luckily Angular provides the ability to accomplish this. The method includes using ng-template
, ng-container
, and ngTemplateOutlet
.
Before getting to the end solution, let’s look at an example of the data and how it’s output without using ng-template
.
export class ListComponent {
links = [
{ internal: true, display: "Home", url: "/" },
{ internal: false, display: "External", url: "https://test.com" },
];
}
<ul>
<li *ngFor="let link of links">
<a *ngIf="link.internal" [routerLink]="link.url">
<img src="/assets/icon.svg" alt="">
<span>{{ link.display }}</span>
</a>
<a *ngIf="!link.internal" [attr.href]="link.url">
<img src="/assets/icon.svg" alt="">
<span>{{ link.display }}</span>
</a>
</li>
</ul>
In this method, we have two *ngIf
directives on two separate a
tags, and the inner content of the link is the same in both cases. If that inner content changes, we have to make the change to both places or else there are inconsistencies in the layout. This is not ideal; we are repeating ourselves and there are multiple locations where we can introduce bugs.
Angular provides a much more elegant solution to our problem. Our TypeScript code from above will remain the same, but we can have a lot less duplication in the HTML by using a couple special Angular tags. First I’ll show the HTML, and then we’ll discuss the different pieces.
<ul>
<li *ngFor="let link of links">
<a *ngIf="link.internal; else externalLink" [routerLink]="link.url">
<ng-container
[ngTemplateOutlet]="linkLayout"
[ngTemplateOutletContext]="{ link: link }"
></ng-container>
</a>
<ng-template #externalLink>
<a [attr.href]="link.url">
<ng-container
[ngTemplateOutlet]="linkLayout"
[ngTemplateOutletContext]="{ link: link }"
></ng-container>
</a>
</ng-template>
</li>
</ul>
<ng-template #linkLayout let-link="link">
<img src="/assets/icon.svg" alt="" />
<span>{{ link.display }}</span>
</ng-template>
There’s a lot going on here, so let’s break it down. We’ll start with the *ngIf
on the a
tag.
<a *ngIf="link.internal; else externalLink" [routerLink]="link.url">
<ng-container
[ngTemplateOutlet]="linkLayout"
[ngTemplateOutletContext]="{ link: link }"
></ng-container>
</a>
<ng-template #externalLink>
<a [attr.href]="link.url">
<ng-container
[ngTemplateOutlet]="linkLayout"
[ngTemplateOutletContext]="{ link: link }"
></ng-container>
</a>
</ng-template>
The *ngIf
directive has an expression listed: if link.internal
evaluates to true
, then show this a
tag. If it’s false, output the ng-template
tag that’s referenced by the externalLink
local template variable. This is how we can either navigate to a new route that’s part of the Angular app or external to the app. This is a method that can be used in any situation where your *ngIf
needs an else
clause.
Next up, let’s look at what’s going on with the ng-container
inside both of the a
tags in the example.
<ng-container
[ngTemplateOutlet]="linkLayout"
[ngTemplateOutletContext]="{ link: link }"
></ng-container>
You can read more about the ng-container
element in the Angular docs, but at a high level it’s a special element that can hold structural directives without adding new elements to the DOM. It can also be used in situations like this, with the ngTemplateOutlet
structural directive. The ngTemplateOutlet
directive determines what ng-template
will be output on the page inside the ng-container
. The context for the template, or needed variables, can be declared with the ngTemplateOutletContext
directive. In the above case, we are saying that the #linkLayout
content should be output on the page, and that there should be a variable called link
that will be used inside the ng-template
. The contents of the ng-template tag can be placed anywhere in the HTML file, though I’ve placed them at the bottom in this example.
<ng-template #linkLayout let-link="link">
<img src="/assets/icon.svg" alt="" />
<span>{{ link.display }}</span>
</ng-template>
This template will be output on the screen anywhere it’s referenced. In this case, inside both a
tags. If we want to change the layout inside the a
tags, we need only change this one spot in the HTML. Everything will be kept in sync, and we have fewer possibilities of inconsistencies in the component.
There is one alternate way of declaring the ngTemplateOutlet
. The result will be the same as the method shown above.
<ng-container
*ngTemplateOutlet="linkLayout; context: { link: link }"
></ng-container>
The above method limits the duplication to a certain degree, especially for the content inside the a
tag. The example here is a fairly simple layout. This method becomes more useful when the internal layout becomes more complicated. That inner layout is defined once and reused in multiple locations. You could create a new component if you wanted, but that can introduce complexity sometimes as well.
Knowing how to use ng-template
, ng-container
, and ngTemplateOutlet
can allow you to effectively output the content of a component with minimal duplication.
Original article source at: https://www.prestonlamb.com/
1654234920
Angular framework always evolves and gets better and better with every release. This time really big changes are coming! One of the most significant changes is Standalone components that allow us to build angular applications without @NgModules. Yes, it is still in Developer Preview mode, so the API might change but we can see already the direction and play around with it and start adjusting our libraries and projects. What do you think about it? Let's discuss it in the comments!
🕒 Time Codes:
00:00:00 - Intro;
00:00:28 - Motivation and Project onboarding;
00:04:58 - Updating project to Angular 14;
00:07:46 - Make the first Standalone component;
00:14:42 - Lazy-Loading and Standalone components;
00:19:00 - Bootstraping application without NgModule;
00:23:19 - Outro;
Initial project state on GitHub:
https://github.com/DMezhenskyi/angular-standalone-components-example
Finished project state on GitHub:
https://github.com/DMezhenskyi/angular-standalone-components-example/tree/standalone-components
#angular #webdevelopment #ng
1654148460
In this video, you will learn how to build a production-ready chat application just in a few hours using GetStream, Firebase, and Angular. First of all, we will build basic authentication for the application using Firebase. Then using Firebase Cloud Functions, we will connect and synchronize Firebase Users with GetStream once and after that, we will implement the chat that has all the necessary functionality to have a smooth and full user experience. As the last step, we will deploy a ready app to the Firebase hosting.
Source code on GitHub:
https://github.com/DMezhenskyi/getstream-chat-angular-example
🕒 Time Codes:
00:00:00 - Intro;
00:01:15 - What is Stream IO;
00:03:27 - Project Onboarding;
00:06:35 - Initialization and adding Firebase to the Firebase;
00:12:26 - User Signing Up using Firebase Authentication;
00:23:29 - User Signing Out using Firebase Authentication;
00:25:50 - User Signing In using Firebase Authentication;
00:29:18 - Adding Firebase Router Guards;
00:36:01 - Intro to Stream.io;
00:38:54 - About Integration Stream.io with Firebase Authentication;
00:41:48 - Initialize Firebase Cloud Functions;
00:43:37 - Mapping Firebase user to Stream.io;
00:56:18 - Initializing Stream Chat;
01:06:04 - Retrieve an Auth Token for Stream Chat;
01:11:22 - Start listening for Stream Channels (Chat Rooms);
01:13:19 - Add default styling and adjust tsconfig.json;
01:14:11 - Implementation of the Chat;
01:22:28 - Creating a new Chat Channel;
01:31:25 - Adding users to the Chat;
01:48:32 - Customising Chat View (Channel Preview);
01:52:48 - Logout the Chat user from the Stream;
01:56:31 - How to deploy Angular App to Firebase Hosting;
02:00:12 - Outro;
#angular #stream #firebase #ng #webdevelopment
1653975600
In this video, we will continue to explore angular schematics and I am going to show you have to create a schematic that will generate a custom component for you with an already pre-injected Angular service. This video is an extension of the previous one where we were implementing the ng-add schematic. I hope you will learn something new today and please enjoy the video.
🕒 Time Codes:
00:00:00 - Intro;
00:01:04 - Quick walk through the project;
00:04:23 - Implementing the schematics to generate a custom component;
00:07:56 - What is Schematic Schema;
00:11:57 - Define an interface for options;
00:13:00 - Implementing factory function for the schematics;
00:15:44 - About Schematics Templates;
00:21:37 - Continue work on Schematic factory function;
00:34:08 - How to reuse existing schematics;
00:40:06 - Outro;
Link to the Project on GitHub:
https://github.com/DMezhenskyi/ngx-schematics-lib-example/tree/custom-component-generator
More about Schematics on Angular Docs:
https://angular.io/guide/schematics-for-libraries
#angular #webdevelopment #schematics #ng
1650438938
Angular Schematics is an absolutely awesome and powerful feature that can save you hours of your time. In this video, I will show you how to implement your custom ng-add schematic that can bring the dev experience of your libraries to a completely new level. Once you implement it, other developers will be able to set up your library just by running `ng add ...`. Enjoy watching!
Time Codes:
00:00:00 - Intro;
00:03:13 - Creating the library;
00:05:54 - Set up a local npm registry Verdaccio;
00:09:11 - Start implementing ng-add schematic;
00:21:36 - How to build schematics;
00:33:21 - How to add library Module to the imports array;
00:46:07 - Outro;
Link to the GitHub: https://github.com/DMezhenskyi/ngx-schematics-lib-example
Subscribe: https://www.youtube.com/c/DecodedFrontend/featured
#angular #webdevelopment #schematics #ng