Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/meeroslav/ng-helpers
Various Angular helpers
https://github.com/meeroslav/ng-helpers
Last synced: 19 days ago
JSON representation
Various Angular helpers
- Host: GitHub
- URL: https://github.com/meeroslav/ng-helpers
- Owner: meeroslav
- License: mit
- Created: 2019-08-31T22:15:44.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2021-10-13T13:24:08.000Z (about 3 years ago)
- Last Synced: 2024-10-29T06:56:41.315Z (2 months ago)
- Language: HTML
- Size: 3.18 MB
- Stars: 17
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
> A library that provides helpers for your Angular projects that speed up the development or solve tricky problems.
ng Helpers
Table of contents:
- [Installation](#installation)
- [Package](#package)
- [Fragment component](#fragment-component)
- [Usage](#usage)
- [Let directive](#let-directive)
- [Usage](#usage-1)
- [Media](#media)
- [Usage](#usage-2)
- [Media service](#media-service)
- [Media component](#media-component)
- [Media directive](#media-directive)
- [Common media queries](#common-media-queries)
- [License](#license)## Installation
```
npm install --save ng-helpers
```## Package
This package consists of the following helpers:
- [Fragment component](#fragment-component)
- [Media](#media)### Fragment component
The `Fragment component` provides the solution for cases when you don't want your component template to be wrapped in a named tag. Such cases include:
- having multiple root nodes
- having a native element as a root nodeAn angular component gets wrapped in a single named tag, provided by the `selector` property. Each component must therefore have a single root DOM note wrapping an entire body. There are, however, situations when we would like to have multiple `root` nodes, for example, if our component is to render `li` elements in the `ul`:
With parent template defined as:
```html
```
And component defined as:
```typescript
@Component({
selector: 'my-list',
template: `
`
})
export class MyList {}
```
renders as
```html
- Apple
- Banana
- Orange
```
which is, of course, invalid HTML and might additionally break our styles. What we would like is for it to render as:
```html
- Apple
- Banana
- Orange
```
#### Usage
The `Fragment component` replaces the root element with the contents of the template defined as the first child element.
```typescript
@Component({
selector: 'my-list',
template: `
`
})
export class MyList extends FragmentComponent implements OnInit {
constructor(vcRef: ViewContainerRef) {
super(vcRef);
}
ngOnInit(): void {
this.appendDOM();
}
}
```
and given parent template:
```html
```
will render as:
```html
- Apple
- Banana
- Orange
```
Possible usages are rendering partial `li` lists, table rows or columns or any other parts of DOM that require the specific parent DOM element.
### Let directive
The angular template is often using deep nested object values or observables in multiple places. The common pattern is to use the `ngIf` structural directive to extract the value:
```HTML
Add row
```
The non-so-obvious flaw of the above approach is that whenever the `loadingState` has a falsy value (0, null, false, etc.) the entire block will not be rendered. The `ngLet` solves this by always rendering the inner content and passing the value no matter if falsy or truthy.
#### Usage
Before using the directive we need to include the module.
```typescript
import { LetModule } from 'ng-helpers';
@NgModule({
imports: [
LetModule
]
})
export class AppModule { }
```
Now we can use it in our component templates
```html
The {{ loadingState }} will be available here
```
We can also use it to put deep nested values in variables for better readability:
```html
Name is required.
Name must be at least 4 characters long.
Name cannot be Bob.
```
### Media
The `Media package` consists several utilities used to responsive content handling in Angular. Those utilities include:
- [Media service](#media-service)
- [Media component](#media-component)
- [Media directive](#media-directive)
You can read more about the motivation in my blog post [Responsive Angular Components](https://missing-manual.com/responsive-angular/). It's an upgrade from [CSS based responsive design by media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries) as it allows us to manipulate the actual content of the DOM instead of just it's visibility. By having too many differences between responsive states we are polluting the DOM by keeping there elements that are not visible.
This can be avoided in Angular by using services, directives or components that will not be rendered unless the certain media query is matched. For example we could use the service to fetch data from different endpoints depending on media or use a component to optionally render a certain DOM block.
#### Usage
In order to use any of the utility parts of the media package we need to include the `MediaModule`:
```typescript
import { MediaModule } from 'ng-helpers';
@NgModule({
imports: [
MediaModule
]
})
export class AppModule { }
```
#### Media service
The `Media service` is a service that exposes an Observable returning matched state of the given media queries.
Usage:
```typescript
@Component({
selector: 'foo-bar',
template: `
I am shown only in the portrait mode
`
})
class FooBarComponent {
private sub: Subscription;
constructor(private readonly mediaService: MediaService) {};
ngOnInit() {
// initialize listener
this.mediaService.setQuery('(orientation: portrait)');
// subscribe to changes programatically or via template
this.mediaService.match$
.pipe(
distinctUntilChanged(),
map(isPortrait => isPortrait ? 'Potrait' : 'Landscape')
)
.subscribe(orientation => console.log(`Orientation changed! New: ${orientation}`));
}
}
```
> In order to avoid memory leaks don't forget to unsubscribe all the listeners! The observable will be automatically closed when service is destroyed.
#### Media component
The `Media component` is an angular wrapper component for manipulating the rendering of the content based on the matched media queries.
Usage:
```typescript
@Component({
selector: 'foo-bar',
template: `
I am visible only on desktop
I am visible only on portrait mode
`
})
class FooBarComponent { }
```
#### Media directive
The `Media directive` is a structural directive for manipulating the content of the template based on the matched media queries.
Usage:
```html
```
#### Common media queries
Some of the most common media queries:
| Query | Result |
| - | - |
| `(max-width: 768px)` | Used for mobile views |
| `(min-width: 769px) and (max-width: 1200px)` | Standard browsers size |
| `(min-width: 1201px) and (max-width: 1400px)` | Wide browsers |
| `(min-width: 1401px)` | Ultra-wide browser |
| `(orientation: landscape)` | Landscape mode on handheld device or if width > height |
| `(orientation: portrait)` | Portrait mode on handheld device or height > width |
You can find more on [CSS Tricks post](https://css-tricks.com/snippets/css/media-queries-for-standard-devices/).
## License
[MIT](http://opensource.org/licenses/MIT)
Copyright (c) 2019-present, Miroslav Jonas