Browse Source

Merge pull request #4133 from abpframework/feat/4022

Added RTL Support for Angular UI
pull/4161/head
Levent Arman Özak 6 years ago
committed by GitHub
parent
commit
4d63df4d11
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 62
      docs/en/UI/Angular/Localization.md
  2. 19
      npm/ng-packs/angular.json
  3. 19
      npm/ng-packs/apps/dev-app/src/app/app.component.ts
  4. 14
      npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts
  5. 8
      npm/ng-packs/packages/core/src/lib/strategies/loading.strategy.ts
  6. 28
      npm/ng-packs/packages/core/src/lib/tests/lazy-load.service.spec.ts
  7. 2
      npm/ng-packs/packages/core/src/lib/tests/loading.strategy.spec.ts
  8. 44
      npm/ng-packs/packages/core/src/lib/tests/localization-utils.spec.ts
  9. 9
      npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts
  10. 11
      npm/ng-packs/packages/theme-basic/src/lib/constants/styles.ts
  11. 4
      npm/ng-packs/packages/theme-shared/src/lib/components/table/table.component.html
  12. 20
      npm/ng-packs/packages/theme-shared/src/lib/components/table/table.component.ts
  13. 6
      npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts
  14. 1
      npm/ng-packs/packages/theme-shared/src/lib/handlers/index.ts
  15. 96
      npm/ng-packs/packages/theme-shared/src/lib/handlers/lazy-style.handler.ts
  16. 2
      npm/ng-packs/packages/theme-shared/src/lib/models/common.ts
  17. 66
      npm/ng-packs/packages/theme-shared/src/lib/tests/lazy-style.handler.spec.ts
  18. 7
      npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts
  19. 1
      npm/ng-packs/packages/theme-shared/src/lib/tokens/index.ts
  20. 3
      npm/ng-packs/packages/theme-shared/src/lib/tokens/lazy-styles.token.ts
  21. 3
      npm/ng-packs/packages/theme-shared/src/public-api.ts
  22. 15
      templates/app/angular/angular.json
  23. 19
      templates/app/angular/src/app/app.component.ts

62
docs/en/UI/Angular/Localization.md

@ -130,6 +130,68 @@ this.store.selectSnapshot(
Localization resources are stored in the `localization` property of `ConfigState`.
## RTL Support
As of v2.9 ABP has RTL support. If you are generating a new project with v2.9 and above, everything is set, you do not need to do any changes. If you are migrating your project from an earlier version, please follow the 2 steps below:
#### Step 1. Create Chunks for Bootstrap LTR and RTL
Find [styles configuration in angular.json](https://angular.io/guide/workspace-config#style-script-config) and make sure the chunks in your project has `bootstrap-rtl.min` and `bootstrap-ltr.min` as shown below.
```json
{
"projects": {
"MyProjectName": {
"architect": {
"build": {
"options": {
"styles": [
{
"input": "node_modules/@abp/ng.theme.shared/styles/bootstrap-rtl.min.css",
"inject": false,
"bundleName": "bootstrap-rtl.min"
},
{
"input": "node_modules/bootstrap/dist/css/bootstrap.min.css",
"inject": true,
"bundleName": "bootstrap-ltr.min"
},
{
"input": "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
"inject": true,
"bundleName": "fontawesome-all.min"
},
{
"input": "node_modules/@fortawesome/fontawesome-free/css/v4-shims.min.css",
"inject": true,
"bundleName": "fontawesome-v4-shims.min"
},
"apps/dev-app/src/styles.scss"
],
}
}
}
}
}
}
#### Step 2. Clear Lazy Loaded Fontawesome in AppComponent
If you have created and injected chunks for Fontawesome as seen above, you no longer need the lazy loading in the `AppComponent` which was implemented before v2.9. Simply remove them. The `AppComponent` in the template of the new version looks like this:
```js
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<abp-loader-bar></abp-loader-bar>
<router-outlet></router-outlet>
`,
})
export class AppComponent {}
```
## See Also

19
npm/ng-packs/angular.json

@ -440,18 +440,27 @@
"assets": ["apps/dev-app/src/favicon.ico", "apps/dev-app/src/assets"],
"extractCss": true,
"styles": [
"apps/dev-app/src/styles.scss",
"node_modules/bootstrap/dist/css/bootstrap.min.css",
{
"input": "node_modules/@abp/ng.theme.shared/styles/bootstrap-rtl.min.css",
"inject": false,
"bundleName": "bootstrap-rtl.min"
},
{
"input": "node_modules/bootstrap/dist/css/bootstrap.min.css",
"inject": true,
"bundleName": "bootstrap-ltr.min"
},
{
"input": "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
"lazy": true,
"inject": true,
"bundleName": "fontawesome-all.min"
},
{
"input": "node_modules/@fortawesome/fontawesome-free/css/v4-shims.min.css",
"lazy": true,
"inject": true,
"bundleName": "fontawesome-v4-shims.min"
}
},
"apps/dev-app/src/styles.scss"
],
"scripts": []
},

19
npm/ng-packs/apps/dev-app/src/app/app.component.ts

@ -1,6 +1,4 @@
import { LazyLoadService, LOADING_STRATEGY } from '@abp/ng.core';
import { Component, OnInit } from '@angular/core';
import { forkJoin } from 'rxjs';
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
@ -9,17 +7,4 @@ import { forkJoin } from 'rxjs';
<router-outlet></router-outlet>
`,
})
export class AppComponent implements OnInit {
constructor(private lazyLoadService: LazyLoadService) {}
ngOnInit() {
forkJoin(
this.lazyLoadService.load(
LOADING_STRATEGY.PrependAnonymousStyleToHead('fontawesome-v4-shims.min.css'),
),
this.lazyLoadService.load(
LOADING_STRATEGY.PrependAnonymousStyleToHead('fontawesome-all.min.css'),
),
).subscribe();
}
}
export class AppComponent {}

14
npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts

@ -8,7 +8,7 @@ import { uuid } from '../utils';
providedIn: 'root',
})
export class LazyLoadService {
readonly loaded = new Set();
readonly loaded = new Map<string, HTMLScriptElement | HTMLLinkElement>();
loadedLibraries: { [url: string]: ReplaySubject<void> } = {};
@ -45,7 +45,7 @@ export class LazyLoadService {
throwError(new CustomEvent('error')),
),
),
tap(() => this.loaded.add(strategy.path)),
tap(() => this.loaded.set(strategy.path, strategy.element)),
delay(100),
shareReplay({ bufferSize: 1, refCount: true }),
);
@ -113,4 +113,14 @@ export class LazyLoadService {
});
});
}
remove(path: string): boolean {
const element = this.loaded.get(path);
if (!element) return false;
element.parentNode.removeChild(element);
this.loaded.delete(path);
return true;
}
}

8
npm/ng-packs/packages/core/src/lib/strategies/loading.strategy.ts

@ -5,6 +5,8 @@ import { CrossOriginStrategy, CROSS_ORIGIN_STRATEGY } from './cross-origin.strat
import { DomStrategy, DOM_STRATEGY } from './dom.strategy';
export abstract class LoadingStrategy<T extends HTMLScriptElement | HTMLLinkElement = any> {
element: T;
constructor(
public path: string,
protected domStrategy: DomStrategy = DOM_STRATEGY.AppendToHead(),
@ -14,10 +16,10 @@ export abstract class LoadingStrategy<T extends HTMLScriptElement | HTMLLinkElem
abstract createElement(): T;
createStream<E extends Event>(): Observable<E> {
this.element = this.createElement();
return of(null).pipe(
switchMap(() =>
fromLazyLoad<E>(this.createElement(), this.domStrategy, this.crossOriginStrategy),
),
switchMap(() => fromLazyLoad<E>(this.element, this.domStrategy, this.crossOriginStrategy)),
);
}
}

28
npm/ng-packs/packages/core/src/lib/tests/lazy-load.service.spec.ts

@ -49,7 +49,7 @@ describe('LazyLoadService', () => {
it('should emit a custom load event if loaded if resource is loaded before', done => {
const loadEvent = new CustomEvent('load');
service.loaded.add(strategy.path);
service.loaded.set(strategy.path, null);
service.load(strategy).subscribe(event => {
expect(event).toEqual(loadEvent);
@ -57,6 +57,32 @@ describe('LazyLoadService', () => {
});
});
});
describe('#remove', () => {
const service = new LazyLoadService();
it('should remove an already lazy loaded element and return true', () => {
const script = document.createElement('script');
document.body.appendChild(script);
service.loaded.set('x', script);
expect(document.body.lastElementChild).toBe(script);
const result = service.remove('x');
expect(document.body.lastElementChild).toBeNull();
expect(service.loaded.has('x')).toBe(false);
expect(result).toBe(true);
});
it('should return false when path not found', () => {
service.loaded.set('foo', null);
const result = service.remove('bar');
expect(result).toBe(false);
});
});
});
describe('LazyLoadService (Deprecated)', () => {

2
npm/ng-packs/packages/core/src/lib/tests/loading.strategy.spec.ts

@ -39,6 +39,7 @@ describe('ScriptLoadingStrategy', () => {
const strategy = new ScriptLoadingStrategy(path, domStrategy, crossOriginStrategy);
strategy.createStream<CustomEvent>().subscribe(event => {
expect(strategy.element.tagName).toBe('SCRIPT');
expect(event.detail.crossOrigin).toBe('use-credentials');
done();
});
@ -78,6 +79,7 @@ describe('StyleLoadingStrategy', () => {
const strategy = new StyleLoadingStrategy(path, domStrategy, crossOriginStrategy);
strategy.createStream<CustomEvent>().subscribe(event => {
expect(strategy.element.tagName).toBe('LINK');
expect(event.detail.crossOrigin).toBe('use-credentials');
done();
});

44
npm/ng-packs/packages/core/src/lib/tests/localization-utils.spec.ts

@ -2,9 +2,53 @@ import {
createLocalizationPipeKeyGenerator,
createLocalizer,
createLocalizerWithFallback,
getLocaleDirection,
} from '../utils/localization-utils';
describe('Localization Utils', () => {
describe('#getLocaleDirection', () => {
test.each`
locale | expected
${undefined} | ${'ltr'}
${null} | ${'ltr'}
${''} | ${'ltr'}
${'en'} | ${'ltr'}
${'en-US'} | ${'ltr'}
${'pt'} | ${'ltr'}
${'pt-PT'} | ${'ltr'}
${'ar'} | ${'rtl'}
${'ar-AE'} | ${'rtl'}
${'ar-QA'} | ${'rtl'}
${'ckb'} | ${'rtl'}
${'ckb-IR'} | ${'rtl'}
${'fa'} | ${'rtl'}
${'fa-AF'} | ${'rtl'}
${'he'} | ${'rtl'}
${'ks'} | ${'rtl'}
${'ksb'} | ${'ltr'}
${'ksf'} | ${'ltr'}
${'ksh'} | ${'ltr'}
${'lrc'} | ${'rtl'}
${'lrc-IQ'} | ${'rtl'}
${'mzn'} | ${'rtl'}
${'pa'} | ${'ltr'}
${'pa-Arab'} | ${'rtl'}
${'ps'} | ${'rtl'}
${'ps-PK'} | ${'rtl'}
${'sd'} | ${'rtl'}
${'ug'} | ${'rtl'}
${'ur'} | ${'rtl'}
${'ur-IN'} | ${'rtl'}
${'uz'} | ${'ltr'}
${'uz-Arab'} | ${'rtl'}
${'yi'} | ${'rtl'}
${'zh'} | ${'ltr'}
${'zh-Hans'} | ${'ltr'}
`('should return $expected when $locale is given as parameter', ({ locale, expected }) => {
expect(getLocaleDirection(locale)).toBe(expected);
});
});
describe('#createLocalizer', () => {
const localize = createLocalizer({
values: { foo: { bar: 'baz' }, x: { y: 'z' } },

9
npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts

@ -1,5 +1,14 @@
import { ApplicationConfiguration } from '../models/application-configuration';
// This will not be necessary when only Angukar 9.1+ is supported
export function getLocaleDirection(locale: string): 'ltr' | 'rtl' {
return /^(ar(-[A-Z]{2})?|ckb(-IR)?|fa(-AF)?|he|ks|lrc(-IQ)?|mzn|pa-Arab|ps(-PK)?|sd|ug|ur(-IN)?|uz-Arab|yi)$/.test(
locale,
)
? 'rtl'
: 'ltr';
}
export function createLocalizer(localization: ApplicationConfiguration.Localization) {
return (resourceName: string, key: string, defaultValue: string) => {
if (resourceName === '_') return key;

11
npm/ng-packs/packages/theme-basic/src/lib/constants/styles.ts

@ -2,7 +2,6 @@ export default `
.content-header-title {
font-size: 24px;
}
.entry-row {
margin-bottom: 15px;
}
@ -26,17 +25,25 @@ export default `
border-radius: 0.25rem;
min-height: 44px;
}
[dir=rtl] .navbar .dropdown-menu a {
text-align: right!important;
}
.navbar .dropdown-submenu a::after {
transform: rotate(-90deg);
position: absolute;
right: 16px;
top: 18px;
}
[dir=rtl] .navbar .dropdown-submenu a::after {
transform: rotate(90deg);
left: 16px;
right: auto;
top: 20px;
}
.navbar .dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
}
.card-header .btn {
padding: 2px 6px;
}

4
npm/ng-packs/packages/theme-shared/src/lib/components/table/table.component.html

@ -21,7 +21,7 @@
<div class="ui-table-scrollable-wrapper">
<div class="ui-table-scrollable-view"></div>
<div class="ui-table-scrollable-header ui-widget-header">
<div [style.margin-left.px]="-bodyScrollLeft" class="ui-table-scrollable-header-box">
<div #header class="ui-table-scrollable-header-box">
<table class="ui-table-scrollable-header-table">
<ng-container *ngTemplateOutlet="colGroup"></ng-container>
<ng-container *ngTemplateOutlet="head"></ng-container>
@ -31,7 +31,7 @@
</div>
<div
#scrollableBody
(scroll)="bodyScrollLeft = scrollableBody.scrollLeft"
(scroll)="header.style.margin = marginCalculator(scrollableBody)"
class="ui-table-scrollable-body"
[style.max-height]="scrollHeight"
>

20
npm/ng-packs/packages/theme-shared/src/lib/components/table/table.component.ts

@ -1,9 +1,9 @@
import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
Input,
OnInit,
Output,
TemplateRef,
TrackByFunction,
@ -17,7 +17,7 @@ import {
styleUrls: ['table.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class TableComponent {
export class TableComponent implements OnInit {
private _totalRecords: number;
bodyScrollLeft = 0;
@ -84,7 +84,23 @@ export class TableComponent {
return this.value.slice(start, start + this.rows);
}
marginCalculator: MarginCalculator;
trackByFn: TrackByFunction<any> = (_, value) => {
return typeof value === 'object' ? value[this.trackingProp] || value : value;
};
ngOnInit() {
this.marginCalculator = document.body.dir === 'rtl' ? rtlCalculator : ltrCalculator;
}
}
function ltrCalculator(div: HTMLDivElement): string {
return `0 auto 0 -${div.scrollLeft}px`;
}
function rtlCalculator(div: HTMLDivElement): string {
return `0 ${-(div.scrollWidth - div.clientWidth - div.scrollLeft)}px 0 auto`;
}
type MarginCalculator = (div: HTMLDivElement) => string;

6
npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts

@ -13,6 +13,10 @@ export default `
text-align: right;
}
[dir=rtl] .data-tables-filter {
text-align: left;
}
.pointer {
cursor: pointer;
}
@ -155,3 +159,5 @@ export default `
/* </animations */
`;
export const BOOTSTRAP = 'bootstrap-{{dir}}.min.css';

1
npm/ng-packs/packages/theme-shared/src/lib/handlers/index.ts

@ -1 +1,2 @@
export * from './error.handler';
export * from './lazy-style.handler';

96
npm/ng-packs/packages/theme-shared/src/lib/handlers/lazy-style.handler.ts

@ -0,0 +1,96 @@
import {
getLocaleDirection,
LazyLoadService,
LOADING_STRATEGY,
LocalizationService,
} from '@abp/ng.core';
import { Injectable, Injector } from '@angular/core';
import { map, startWith } from 'rxjs/operators';
import { BOOTSTRAP } from '../constants/styles';
import { LocaleDirection } from '../models/common';
import { LAZY_STYLES } from '../tokens/lazy-styles.token';
@Injectable({
providedIn: 'root',
})
export class LazyStyleHandler {
private lazyLoad: LazyLoadService;
private styles: string[];
private _dir: LocaleDirection = 'ltr';
set dir(dir: LocaleDirection) {
if (dir === this._dir) return;
this.switchCSS(dir);
this.setBodyDir(dir);
this._dir = dir;
}
get dir(): LocaleDirection {
return this._dir;
}
constructor(injector: Injector) {
this.setStyles(injector);
this.setLazyLoad(injector);
this.listenToLanguageChanges(injector);
}
private getLoadedBootstrap(): LoadedStyle {
const href = createLazyStyleHref(BOOTSTRAP, this.dir);
const selector = `[href$="${href}"]`;
const link = document.querySelector<HTMLLinkElement>(selector);
return { href, link };
}
private listenToLanguageChanges(injector: Injector) {
const l10n = injector.get(LocalizationService);
// will always listen, no need to unsubscribe
l10n.languageChange
.pipe(
map(({ payload }) => payload),
startWith(l10n.currentLang),
)
.subscribe(locale => {
this.dir = getLocaleDirection(locale);
});
}
private setBodyDir(dir: LocaleDirection) {
document.body.dir = dir;
}
private setLazyLoad(injector: Injector) {
this.lazyLoad = injector.get(LazyLoadService);
const { href, link } = this.getLoadedBootstrap();
this.lazyLoad.loaded.set(href, link);
}
private setStyles(injector: Injector) {
this.styles = injector.get(LAZY_STYLES, [BOOTSTRAP]);
}
private switchCSS(dir: LocaleDirection) {
this.styles.forEach(style => {
const oldHref = createLazyStyleHref(style, this.dir);
const newHref = createLazyStyleHref(style, dir);
const strategy = LOADING_STRATEGY.PrependAnonymousStyleToHead(newHref);
this.lazyLoad.load(strategy).subscribe(() => this.lazyLoad.remove(oldHref));
});
}
}
export function createLazyStyleHref(style: string, dir: string): string {
return style.replace(/{{\s*dir\s*}}/g, dir);
}
export function initLazyStyleHandler(injector: Injector) {
return () => new LazyStyleHandler(injector);
}
interface LoadedStyle {
href: string;
link: HTMLLinkElement;
}

2
npm/ng-packs/packages/theme-shared/src/lib/models/common.ts

@ -14,3 +14,5 @@ export interface HttpErrorConfig {
hideCloseIcon?: boolean;
};
}
export type LocaleDirection = 'ltr' | 'rtl';

66
npm/ng-packs/packages/theme-shared/src/lib/tests/lazy-style.handler.spec.ts

@ -0,0 +1,66 @@
import { LazyLoadService, LOADING_STRATEGY, LocalizationService } from '@abp/ng.core';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
import { EMPTY, of } from 'rxjs';
import { BOOTSTRAP } from '../constants/styles';
import { createLazyStyleHref, initLazyStyleHandler, LazyStyleHandler } from '../handlers';
const languageChange = of({ payload: 'en' });
describe('LazyStyleHandler', () => {
let spectator: SpectatorService<LazyStyleHandler>;
let handler: LazyStyleHandler;
let lazyLoad: LazyLoadService;
const createService = createServiceFactory({
service: LazyStyleHandler,
providers: [
{
provide: LocalizationService,
useValue: { currentLang: 'en', languageChange },
},
],
});
beforeEach(() => {
spectator = createService();
handler = spectator.service;
lazyLoad = handler['lazyLoad'];
});
describe('#dir', () => {
it('should initially be "ltr"', () => {
expect(handler.dir).toBe('ltr');
});
it('should set bootstrap to rtl', () => {
const oldHref = createLazyStyleHref(BOOTSTRAP, 'ltr');
const newHref = createLazyStyleHref(BOOTSTRAP, 'rtl');
lazyLoad.loaded.set(newHref, null); // avoid actual loading
const load = jest.spyOn(lazyLoad, 'load');
const remove = jest.spyOn(lazyLoad, 'remove');
const strategy = LOADING_STRATEGY.PrependAnonymousStyleToHead(newHref);
handler.dir = 'rtl';
expect(load).toHaveBeenCalledWith(strategy);
expect(remove).toHaveBeenCalledWith(oldHref);
});
});
});
describe('initLazyStyleHandler', () => {
it('should return a LazyStyleHandler factory', () => {
const generator = (function*() {
yield undefined; // LAZY_STYLES
yield { loaded: new Map() }; // LazyLoadService
yield { currentLang: 'en', languageChange: EMPTY }; // LocalizationService
})();
const injector = {
get: () => generator.next().value as any,
};
const factory = initLazyStyleHandler(injector);
expect(factory()).toBeInstanceOf(LazyStyleHandler);
});
});

7
npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts

@ -22,6 +22,7 @@ import styles from './constants/styles';
import { LoadingDirective } from './directives/loading.directive';
import { TableSortDirective } from './directives/table-sort.directive';
import { ErrorHandler } from './handlers/error.handler';
import { initLazyStyleHandler } from './handlers/lazy-style.handler';
import { RootParams } from './models/common';
import { THEME_SHARED_APPEND_CONTENT } from './tokens/append-content.token';
import { httpErrorConfigFactory, HTTP_ERROR_CONFIG } from './tokens/http-error.token';
@ -104,6 +105,12 @@ export class ThemeSharedModule {
deps: [THEME_SHARED_APPEND_CONTENT],
useFactory: noop,
},
{
provide: APP_INITIALIZER,
multi: true,
deps: [Injector],
useFactory: initLazyStyleHandler,
},
{ provide: HTTP_ERROR_CONFIG, useValue: options.httpErrorConfig },
{
provide: 'HTTP_ERROR_CONFIG',

1
npm/ng-packs/packages/theme-shared/src/lib/tokens/index.ts

@ -1,2 +1,3 @@
export * from './append-content.token';
export * from './http-error.token';
export * from './lazy-styles.token';

3
npm/ng-packs/packages/theme-shared/src/lib/tokens/lazy-styles.token.ts

@ -0,0 +1,3 @@
import { InjectionToken } from '@angular/core';
export const LAZY_STYLES = new InjectionToken<string[]>('LAZY_STYLES');

3
npm/ng-packs/packages/theme-shared/src/public-api.ts

@ -5,8 +5,9 @@
export * from './lib/theme-shared.module';
export * from './lib/animations';
export * from './lib/components';
export { BOOTSTRAP } from './lib/constants/styles';
export * from './lib/directives';
export * from './lib/handlers';
export { ErrorHandler } from './lib/handlers';
export * from './lib/models';
export * from './lib/services';
export * from './lib/tokens';

15
templates/app/angular/angular.json

@ -26,22 +26,27 @@
"extractCss": true,
"assets": ["src/favicon.ico", "src/assets"],
"styles": [
{
"input": "node_modules/@abp/ng.theme.shared/styles/bootstrap-rtl.min.css",
"inject": false,
"bundleName": "bootstrap-rtl.min"
},
{
"input": "node_modules/bootstrap/dist/css/bootstrap.min.css",
"inject": true,
"bundleName": "bootstrap.min"
"bundleName": "bootstrap-ltr.min"
},
"src/styles.scss",
{
"input": "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
"inject": false,
"inject": true,
"bundleName": "fontawesome-all.min"
},
{
"input": "node_modules/@fortawesome/fontawesome-free/css/v4-shims.min.css",
"inject": false,
"inject": true,
"bundleName": "fontawesome-v4-shims.min"
}
},
"src/styles.scss"
],
"scripts": []
},

19
templates/app/angular/src/app/app.component.ts

@ -1,6 +1,4 @@
import { LazyLoadService, LOADING_STRATEGY } from '@abp/ng.core';
import { Component, OnInit } from '@angular/core';
import { forkJoin } from 'rxjs';
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
@ -9,17 +7,4 @@ import { forkJoin } from 'rxjs';
<router-outlet></router-outlet>
`,
})
export class AppComponent implements OnInit {
constructor(private lazyLoadService: LazyLoadService) {}
ngOnInit() {
forkJoin(
this.lazyLoadService.load(
LOADING_STRATEGY.PrependAnonymousStyleToHead('fontawesome-v4-shims.min.css')
),
this.lazyLoadService.load(
LOADING_STRATEGY.PrependAnonymousStyleToHead('fontawesome-all.min.css')
)
).subscribe();
}
}
export class AppComponent {}

Loading…
Cancel
Save