Angular CLI - How to reference image paths in reusable components - image

Need help figuring out how to include images in a reusable component that is referenced in another app.
For example, I have an Angular App, let's call it UI-Common, that contains common components and another Angular App, let's call it Command-Center, that will use those common components.
In UI-Common, there is a component called my-control.component that is defined as follows:
[my-control.component.html]
<div>
<img src="assets/images/myImage.png"/>
<div class"username" *ngIf="user">
<p><strong>{{user.companyName}}</strong></p>
<p>{{user.firstName + ' ' + user.lastName}}</p>
</div>
[my-control.component.ts]
import { Component, Input } from '#angular/core';
import { User } from '../../models/user';
#Component({
selector: 'my-control',
templateUrl: './my-control.component.html',
styleUrls: ['./my-control.component.scss'],
})
export class MyControlComponent {
#Input() user: User;
constructor() {
}
}
In Command-Center, it adds UI-Common as a dependency in the package.json. A Command-Center component is created and uses my-control.component as follows:
[app.module.ts]
...
import { HomeComponent } from './home/home.component';
import { MyControlComponent } from 'ui-common';
#NgModule({
declarations: [
...,
HomeComponent,
MyControlComponent,
...
],
...
})
export class AppModule { }
[home.component.html]
<my-control [user]=user></my-control>
<div class="homeContent">
blah blah blah...
</div>
[home.component.ts]
import { Component } from '#angular/core';
import { User } from 'ui-common';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent {
user: User;
constructor() {
this.user = new User();
this.user.companyName = 'iHeartMedia';
this.user.firstName = 'John';
this.user.lastName = 'Smith';
}
}
The problem is the image on my-control when running from Command-Center does not load at all. This appears to be because the image path being used "assets/images/myImage.png" does not exist in Command-Center. I don't want to save a copy of the image in the Command-Center's assets folder. How do I properly handle images in the common component?

Found this Angular CLI feature request: https://github.com/angular/angular-cli/issues/3555
The Angular app can be configured to copy files from a relative file path to a folder within the app's distribution directory. This allows us to get access to images from within the node_modules folder without having to manually copy the images into the local assets folder.
After updating to the latest version of Angular CLI (1.2.1) I modified my angular-cli.json file as follows:
{
...
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico",
"version.txt",
{
"glob": "**/*",
"input": "../node_modules/ui-common/src/assets/images",
"output": "./assets/images"
}
],
...
}
Now all images that are in the UI-Common app are accessible to the Command-Center app.
More details about the configuration here: https://github.com/angular/angular-cli/wiki/stories-asset-configuration

import {APP_BASE_HREF} from '#angular/common';
#NgModule({
declarations: [ ... ],
imports: [ ... ],
providers: [{provide: APP_BASE_HREF, useValue : '/' }]
]);
I think you need to do something like this for the module you want to to use the image in.

Related

Navigating from single page view to side-menu layout in ionic 4

I'd like to build an app using Ionic 4 that simplistically works the following way:
On-boarding page is shown with some images/text
After user clicked 'start' button, some flag onboarded=true is written into local-storage
User redirected to the main app view which is a ion-split-pane containing side-menu layout
Next time when user launches the app, I check if he/she already viewed on-boarding screen (by checking presence of onboarded var in storage) and if it is - I immediately redirect the user to the main app having side-menu layout as I mentioned, omitting on-boarding screen.
I started the project using ionic cli, based on side-menu template and to fulfill logic described above, I modified it the following way:
app.component.ts
import { Component } from '#angular/core';
import { Platform } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { Storage } from '#ionic/storage';
import { Router } from '#angular/router';
#Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>',
})
export class AppComponent {
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private storage: Storage,
private router: Router
) {
this.initializeApp();
}
async initializeApp() {
await this.platform.ready();
this.statusBar.styleDefault();
this.splashScreen.hide();
const onboarded = await this.storage.get('onboarded');
if (onboarded) {
this.router.navigate(['main-app']);
} else {
this.router.navigate(['onboarding']);
}
}
}
onboarding.page.html
<ion-header>
<ion-toolbar>
<ion-title>onboarding</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
Welcome aboard!
<ion-button (click)="start()">Start app!</ion-button>
</ion-content>
onboarding.page.ts
import { Component } from '#angular/core';
import { Storage } from '#ionic/storage';
import { Router } from '#angular/router';
#Component({
selector: 'app-onboarding',
templateUrl: './onboarding.page.html',
styleUrls: ['./onboarding.page.scss'],
})
export class OnboardingPage {
constructor(
private storage: Storage,
private router: Router
) { }
start() {
this.storage.set('onboarded', true);
this.router.navigate(['main-app']);
}
}
main-app.page.html
<ion-app>
<ion-split-pane>
<ion-menu>
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-menu-toggle auto-hide="false" *ngFor="let p of appPages">
<ion-item [routerDirection]="'root'" [routerLink]="[p.url]">
<ion-icon slot="start" [name]="p.icon"></ion-icon>
<ion-label>
{{p.title}}
</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
</ion-content>
</ion-menu>
<ion-router-outlet main></ion-router-outlet>
</ion-split-pane>
</ion-app>
main-app.page.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-main-app',
templateUrl: './main-app.page.html',
styleUrls: ['./main-app.page.scss'],
})
export class MainAppPage {
public appPages = [
{
title: 'Home',
url: '/home',
icon: 'home'
},
{
title: 'List',
url: '/list',
icon: 'list'
}
];
constructor() { }
}
List and Home pages are just empty pages and their content is not important for this example
Problem is that main-app containing side menu and content is not working properly. I know that there is a problem in <ion-router-outlet main></ion-router-outlet>'s usage but couldn't find the right solution.
Does anyone have idea how to make it work?
Thanks!
Andrew.
try adding contentId="content" to your <ion-menu>
ie: <ion-menu contentId="content">
and also add id="content" to your <ion-router-outlet>
ie: <ion-router-outlet id="content" main>
i seem to remember something about the router-outlet not working without that.

Embedded Nativescript Angular code into existing iOS project, Angular 7 throws Error: Error: A Frame must be used to navigate to a Page

When i run iOS xcode project with embedded nativescript frameworks and nativescript code, apps gives error when try to show/load nativescript pages into xcode console:
Error: Error: A Frame must be used to navigate to a Page.
Below are the my Objective-c Function which starts loading NativeScript pages.
- (NSString*) scriptStringToLoad {
NSString *source = #"var platform_1 = require('nativescript-angular/platform');"
"var app_module_1 = require('./app/app.module');"
"var platform = platform_1.platformNativeScriptDynamic();"
"platform.bootstrapModule(app_module_1.AppModule);";
return source;
}
Below is NativeSctipt part:
app.module.ts file code
import { NgModule, NO_ERRORS_SCHEMA } from "#angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
#NgModule({
bootstrap: [
AppComponent
],
imports: [
NativeScriptModule,
AppRoutingModule
],
declarations: [
AppComponent
],
schemas: [
NO_ERRORS_SCHEMA
]
})
export class AppModule { }
app.component.ts file code
import { Component } from "#angular/core";
#Component({
moduleId: module.id,
selector: "ns-app",
templateUrl: "app.component.html"
})
export class AppComponent {
onButtonTap() {
console.log('Hi hello button tapped');
}
}
app.component.html file code
Your app.component.html should only have
<page-router-outlet></page-router-outlet>
and to build you can use tns build with --bundle flag to enable webpack build and check.
You can follow the structure as in this playground sample - play.nativescript.org/?template=play-ng&id=iayuat

JHipster: I can't add thiered party dependency like 'angular-2-dropdown-multiselect'

I have added angular2-dropdown-multiselect in Jhipster angular part. Its not working perfectly as per the angular2-dropdwon-multi select or ngx-treeview I have added the dependency using
npm install angular2-multiselect-dropdown --save
Then I have added the same into app.module.ts
import { AngularMultiSelectModule } from 'angular2-multiselect-dropdown/angular2-multiselect-dropdown';
#NgModule({
// ...
imports: [
AngularMultiSelectModule,
]
// ...
})
Then Try this following example
import { Component, OnInit } from '#angular/core';
export class AppComponent implements OnInit {
dropdownList = [];
selectedItems = [];
dropdownSettings = {};
ngOnInit(){
this.dropdownList = [
{"id":1,"itemName":"India"},
{"id":2,"itemName":"Singapore"},
{"id":3,"itemName":"Australia"},
{"id":4,"itemName":"Canada"},
{"id":5,"itemName":"South Korea"},
{"id":6,"itemName":"Germany"},
{"id":7,"itemName":"France"},
{"id":8,"itemName":"Russia"},
{"id":9,"itemName":"Italy"},
{"id":10,"itemName":"Sweden"}
];
this.selectedItems = [
{"id":2,"itemName":"Singapore"},
{"id":3,"itemName":"Australia"},
{"id":4,"itemName":"Canada"},
{"id":5,"itemName":"South Korea"}
];
this.dropdownSettings = {
singleSelection: false,
text:"Select Countries",
selectAllText:'Select All',
unSelectAllText:'UnSelect All',
enableSearchFilter: true,
classes:"myclass custom-class"
};
}
onItemSelect(item:any){
console.log(item);
console.log(this.selectedItems);
}
OnItemDeSelect(item:any){
console.log(item);
console.log(this.selectedItems);
}
onSelectAll(items: any){
console.log(items);
}
onDeSelectAll(items: any){
console.log(items);
}
}
with HTML
<angular2-multiselect [data]="dropdownList" [(ngModel)]="selectedItems"
[settings]="dropdownSettings"
(onSelect)="onItemSelect($event)"
(onDeSelect)="OnItemDeSelect($event)"
(onSelectAll)="onSelectAll($event)"
(onDeSelectAll)="onDeSelectAll($event)">
</angular2-multiselect>
But after runing yarn serve
it just showing
Please help me
I had a similar problem with another third party library (ngx-treeview) and I also was only getting the html component empty and with no errors in the javascript console.
It was solved after importing the third party library properly following the JHipster project structure. If you want to use an external module in more than one module component, which is common, you need to configure it in shared-libs.module.ts and also add it to imports and to the exports on its #NgModule configuration.
src\main\webapp\app\shared\shared-libs.module.ts
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { CommonModule } from '#angular/common';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { NgJhipsterModule } from 'ng-jhipster';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { CookieModule } from 'ngx-cookie';
import { FontAwesomeModule } from '#fortawesome/angular-fontawesome';
import { TreeviewModule } from 'ngx-treeview';
#NgModule({
imports: [
NgbModule.forRoot(),
NgJhipsterModule.forRoot({
alertAsToast: false,
i18nEnabled: true,
defaultI18nLang: 'en'
}),
InfiniteScrollModule,
CookieModule.forRoot(),
FontAwesomeModule,
TreeviewModule.forRoot() // new third party lib import
],
exports: [FormsModule, CommonModule, NgbModule, NgJhipsterModule,
InfiniteScrollModule, FontAwesomeModule,
TreeviewModule] // new third party lib export
})
export class MyProjectSharedLibsModule {}
Share-libs module is generated by Jhipster and it is by default imported in shared.module which is imported by app.module and also the other modules that are created at start by Jhipster. For more about project structure: https://www.jhipster.tech/using-angular/
However, if you create a new angular module component you need to add the shared module in the imports to be able to use the third parties libraries there.
#NgModule({
...
imports: [MyProjectSharedModule,
RouterModule.forChild([HOME_ROUTE])],
..
})
export class MyProjectAnotherModule {}

NumericTextBox Kendo UI for Angular2 with custom IntlService

I have taken latest RC0 of Kendo UI for Angular2. It's docs mentions use of Internationalization service. I have created custom IntlService and configured it's provider in my App Module. In the component if I use the IntlService dependency then my custom service is invoked, but the NumericTextBox is not calling my service. What's wrong in the following code?
MyIntlService.ts
import { CldrIntlService } from '#progress/kendo-angular-intl';
import { Injectable } from '#angular/core';
#Injectable()
export class MyIntlService extends CldrIntlService {
constructor() {
super("en-US");
console.info('From MyIntlService ctor');
}
formatNumber(value: number, format: string| NumberFormatOptions){
const result = super.formatNumber(value,format);
console.log('In MyIntlService formatNumber');
return result;
}
}
app.module.ts
#NgModule({
imports: [ BrowserModule, InputsModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [{
provide: IntlService,
useClass: MyIntlService
}]
})
export class AppModule { }
app.component
export class AppComponent {
constructor(private intl: IntlService) {
console.log( " From AppComponent " + intl.formatNumber(42, "c"));
}
}
You can file an issue in the GitHub repository ↗. Providing a runnable example demonstrating the issue will be appreciated.

angular2 and nativescript does not work - assertion failed: 15G1004 14A345: libxpc.dylib

I am been having a terrible time getting nativescript to work with angular 2 with the official release. I am zero issues with good ole faction web angular but native script is a different story. NativeScript why will my hello world work? I see nothing.
Thanks
Home:
import {Component} from "#angular/core";
import { Router } from "#angular/router";
#Component({
selector: "home",
template: "hello",
})
export class HomeComponent {
constructor(private router: Router){
}
}
app
import {Component} from "#angular/core";
#Component({
selector: "main",
template: "<page-router-outlet></page-router-outlet>",
})
export class AppComponent {
}
Routes:
import { HomeComponent } from "./pages/home/home.component";
export const routes = [
{ path: "", component: HomeComponent }
];
export const navigatableComponents = [
HomeComponent
];
Modules:
import { NgModule } from "#angular/core";
import { NativeScriptFormsModule } from "nativescript-angular/forms";
import { NativeScriptHttpModule } from "nativescript-angular/http";
import { NativeScriptModule } from "nativescript-angular/platform";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { AppComponent } from "./app.component";
import { HomeComponent } from "./pages/home/home.component";
import { routes, navigatableComponents } from "./app.routes";
#NgModule({
imports: [
NativeScriptModule,
NativeScriptFormsModule,
NativeScriptHttpModule,
NativeScriptRouterModule,
NativeScriptRouterModule.forRoot(routes)
],
declarations: [AppComponent,
...navigatableComponents ],
bootstrap: [AppComponent]
})
export class AppModule {}
Executing before-prepare hook from /Users/Documents/frontend/bootops-mobile-v1/hooks/before-prepare/nativescript-dev-typescript.js
Project successfully prepared (ios)
Transferring project files...
Successfully transferred all files.
Applying changes...
Sep 17 23:05:18 Davids-iMac com.apple.CoreSimulator.SimDevice.D28D29C3-07B6-4B60-B4B0-711475C505DE.launchd_sim[19187] (UIKitApplication:org.nativescript.bootopsmobilev1[0x7351][20309]): Service exited due to Terminated: 15
Successfully synced application org.nativescript.bootopsmobilev1 on device D28D29C3-07B6-4B60-B4B0-711475C505DE.
Sep 17 23:05:19 Davids-iMac bootopsmobilev1[20349]: objc[20349]: Class PLBuildVersion is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/AssetsLibraryServices.framework/AssetsLibraryServices (0x124c81910) and /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/PhotoLibraryServices.framework/PhotoLibraryServices (0x124aab210). One of the two will be used. Which one is undefined.
Sep 17 23:05:19 Davids-iMac bootopsmobilev1[20349]: assertion failed: 15G1004 14A345: libxpc.dylib + 62597 [37A9DF49-35C1-3D93-B854-B35CACF0100F]: 0x7d
Sep 17 23:05:19 Davids-iMac bootopsmobilev1[20349]: CONSOLE LOG file:///app/tns_modules/#angular/core/bundles/core.umd.js:210:20: Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.
Everything in your code snippets looks good except the part with the HomeComponent template, that Component declaration should look like this:
#Component({
selector: "home",
template: `<Label text="hello"></Label>`,
})
export class HomeComponent {
constructor(private router: Router){
}
}
The reason behind this is the fact that in NativeScript there is not webview it is all native components. So in order for your "hello" text to be rendered you need to use the NativeScript Label. This is all true for NativeScript + Angular 2. Your code snippets work correctly on Angular 2 web because the web browser knows how to render that text, on the other hand NativeScripts Angular 2 renderer does not know how to render a text directly because on iOS and Android there is not such rendering and you need to tell it how via the Label tag.
In the index.html, you have to put <selector-for-the-page></selector-for-the-page> You might have different selector.

Resources