Our site is an existing MVC site and we are working on adding and replacing some parts with angular 2 components. We do not have a full angular 2 app to launch, so we are just using bootstrap to launch our components on the pages we want them.
I updated my package.json dependencies from "2.0.0-rc.1" to "~2.2.0" and now have the latest angular 2 files. I can no longer use import { bootstrap } from '#angular/platform-browser-dynamic' and launch my component with: bootstrap(MyCountComponent, [HTTP_PROVIDERS, MyService]);.
Searching it seems to have been updated to import { platformBrowserDynamic } from '#angular/platform-browser-dynamic'; and now I should launch with: platformBrowserDynamic().bootstrapModule(MyCountComponent, [HTTP_PROVIDERS, MyService]);
When I do this I'm getting the browser Console error:
Unhandled Promise rejection: (SystemJS) No NgModule metadata found for 'MyCountComponent'.
Error: No NgModule metadata found for 'MyCountComponent'...
Do I need to convert my components to modules now or is there a new way to bootstrap launch the components without a module?
Here is a code sample.
//mycount.ts
import { MyService } from '../../services/my.service';
import { HTTP_PROVIDERS } from '#angular/http';
import { bootstrap } from '#angular/platform-browser-dynamic'
import { MyCountComponent } from './mycount.component';
bootstrap(MyCountComponent, [HTTP_PROVIDERS, MyService]);
//mycount.component.ts
import { Component } from '#angular/core';
import { NgControl } from '#angular/forms';
import { MyService } from '../../services/my.service';
#Component({
selector: 'mycount',
templateUrl: './app/components/mycount/mycount.component.html'
})
export class MyCountComponent {
constructor(private _myService: MyService) {
}
get mycount() {
return this._myService.mycount;
}
}
//systemjs.config.js
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
'#angular/upgrade': 'npm:#angular/upgrade/bundles/upgrade.umd.js',
'#angular/upgrade/static': 'npm:#angular/upgrade/bundles/upgrade-static.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
}
}
});
})(this);
EDIT
If I have:
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule
],
bootstrap: [MyCountComponent, MyListComponent, MyDetailsComponent],
declarations: [MyCountComponent, MyListComponent, MyDetailsComponent],
exports: [MyCountComponent, MyListComponent, MyDetailsComponent],
providers: [MyService]
})
Is it possible for my page to only load 1 or 2 of the components?
I tried calling it with:
platformBrowserDynamic().bootstrapModule(MyModule, [HttpModule, MyListComponent]);
but I get an error message for any component tags missing from the page.
you need to create main #NgModule where you can import all Services, Components, Directives etc. using #NgModule you can tell your app that which component should bootstrap.
here is official links to understand that #ngModule please go through this: https://angular.io/docs/ts/latest/guide/ngmodule.html
Tips: please use Angular-cli which will create a basic structure of app just in few minutes. using Angular-cli you no need to create structued app or basic setup it will do it for you.
Related
I'm now using vuepress2 with quasar 2.7.1 like this:
import { Quasar } from 'quasar';
export default defineClientAppEnhance(({ app, router, siteData }) => {
app.use(Quasar);
}
#import url(https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons|Material+Icons+Outlined);
#import 'quasar/src/css/variables.sass';
#import 'quasar/src/css/core/colors.sass';
.quasar-comp {
#import 'quasar/src/css/index.sass';
}
/* I wrap the custome component in class .quasar-comp
so that the style from quasar won't conflict with style from vuepress. */
but there are 2 issues:
The style from quasar cannot works on some components, like q-btn-dropdown or q-menu.
It works well on dev mode(npm run docs:dev), but failed to build(npm run docs:build).
✔ Compiling with vite - done
✖ Rendering pages - failed
TypeError: Cannot convert undefined or null to object
at Function.assign (<anonymous>)
at installQuasar (/Users/lxm/Documents/neo/leaneo-docs/node_modules/quasar/dist/quasar.cjs.prod.js:6:15228)
at Object.install (/Users/lxm/Documents/neo/leaneo-docs/node_modules/quasar/dist/quasar.cjs.prod.js:6:479348)
at Object.use (/Users/lxm/Documents/neo/leaneo-docs/node_modules/#vue/runtime-core/dist/runtime-core.cjs.prod.js:3393:28)
at /Users/lxm/Documents/neo/leaneo-docs/docs/.vuepress/dist/.server/app.js:3745:7
at createVueApp (/Users/lxm/Documents/neo/leaneo-docs/docs/.vuepress/dist/.server/app.js:4177:11)
at async /Users/lxm/Documents/neo/leaneo-docs/node_modules/vuepress-vite/node_modules/#vuepress/bundler-vite/lib/build/build.js:49:52
at async /Users/lxm/Documents/neo/leaneo-docs/node_modules/#vuepress/utils/lib/withSpinner.js:12:24
at async build (/Users/lxm/Documents/neo/leaneo-docs/node_modules/vuepress-vite/node_modules/#vuepress/bundler-vite/lib/build/build.js:34:5)
at async /Users/lxm/Documents/neo/leaneo-docs/node_modules/#vuepress/cli/lib/commands/build/createBuild.js:51:5
Is there a better way to make quasar and vuepress works together?
Here is the implementation in Vuepress 2 (beta) and Quasar with Typescript.
First, install Quasar into Vuepress with the new syntax and import all styles:
client.ts:
import { defineClientConfig } from "#vuepress/client";
import { Quasar } from "quasar";
import 'quasar/src/css/index.sass';
export default defineClientConfig({
enhance({app, router, siteData}) {
app.use(Quasar);
},
setup() {},
rootComponents: [],
});
Then, ignore deprecation errors from sass if you're using vite.
config.ts
import { viteBundler } from '#vuepress/bundler-vite'
import { defineUserConfig } from '#vuepress/cli'
export default defineUserConfig({
// your config
...
bundler: viteBundler({
viteOptions: {
css: {
preprocessorOptions: {
scss: {
sassOptions: {
// ignore sass deprecation errors
quietDeps: true
}
}
}
}
},
}),
});
Hope it helps :)
Quasar needs some globales to be defined (ie if it's SSR). My following solution works ONYL on client-side so be sure to wrap your custom-quasar component in <ClientOnly> !
// .vuepress/config.ts
bundler: viteBundler({
viteOptions: {
define: {
__QUASAR_VERSION__: `'dev'`,
__QUASAR_SSR__: false,
__QUASAR_SSR_SERVER__: false,
__QUASAR_SSR_CLIENT__: false,
__QUASAR_SSR_PWA__: false
}
}
}),
// .vuepress/client.ts
import { defineClientConfig } from '#vuepress/client'
import Quasar from "quasar/src/install-quasar.js";
// optionally import your styles here
// import 'quasar/src/css/index.sass';
export default defineClientConfig({
enhance({ app, router, siteData }) {
app.use(Quasar);
},
setup() {
},
rootComponents: [],
});
<!-- README.md -->
<ClientOnly>
<MyComponent />
</ClientOnly>
I am trying to fire a simple notification in Quasar 2:
setup() {
const $q = useQuasar()
$q.notify('hello')
}
This fails with:
Uncaught TypeError: $q.notify is not a function
This is a UMD application that works fine without these two lines - I do not really know where to go from there as the docs say that there is nothing special to configure before using it.
Incindentally, my IDE is suggesting me notify() when typing $q. so at least at that level is it well recognized.
I think you forgot to add notify in plugins(quasar.conf.js).
return {
framework: {
plugins: [
'Notify'
],
}
}
For those using Vue CLI, you will need to work on quasar-user-options.js:
import { Notify } from "quasar";
// To be used on app.use(Quasar, { ... })
export default {
plugins: { Notify },
};
Quasar vite plugin + vue3
In main.ts or main.js, just add these 2 lines :
JS
import { Notify } from "quasar";
.use(Quasar, {
plugins: {
Notify,
}, // import Quasar plugins and add here
})
Here a example of my code :
JS
import { createApp } from 'vue'
import { Quasar } from 'quasar'
import quasarLang from 'quasar/lang/fr'
import { Notify } from "quasar";
import router from './router'
import { createPinia } from 'pinia'
import './style.css'
// Import icon libraries
import '#quasar/extras/material-icons/material-icons.css'
// Import Quasar css
import 'quasar/src/css/index.sass'
import App from './App.vue'
const pinia = createPinia()
createApp(App)
.use(Quasar, {
plugins: {
Notify,
}, // import Quasar plugins and add here
lang: quasarLang,
})
.use(router)
.use(pinia)
.mount('#app')
I'm programming an application with ionic and socket IO, in the app.module.ts the import of the socket needs a config for the url and options. This is hardcoded and i would like have this config dynamically from a form or a storage. I dont want to deploy the application for any change of the ip address or server port and i dont want to use a dns link.
Can you tell me how I can do that ?
I'm using ionic : 5.4.5, Cordova 9.0.0 and deploy on IOS 12.4
Here is my app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { RouteReuseStrategy } from '#angular/router';
import { ErrorHandler } from '#angular/core';
import { IonicModule, IonicRouteStrategy } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '#angular/common/http';
import { SocketIoModule, SocketIoConfig } from 'ng-socket-io';
const config: SocketIoConfig = { url: 'http://192.168.0.17:3001', options: {} };
#NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
HttpClientModule,
SocketIoModule.forRoot(config),
],
providers: [
StatusBar,
SplashScreen,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule { }
Thanks for any response.
app.module.ts is your core application module and it should load fast to allow other modules and components to get ready asap. So adding business logic to it to fetch dynamic config for Socket.io might be suboptimal as you may cause UX issues (longer load time etc).
I would suggest moving the initialization/config of the socket.io away from app.module.ts to another module that gets loaded later in the start-up life cycle of your app.
I had similar requirement and I approached it this way:
-used other socket.io client library that does not require init via a module: https://github.com/socketio/socket.io-client
-created a service and imported this library into it:
import { Injectable } from "#angular/core";
import io from "socket.io-client";
export class FoundationProvider {
public sockets;
}
-created a method that is called after I fetched socket config details and other details from persistence:
initSocketsIO() {
if (this.data.userID && this.state.appIsOnline) {
this.sockets = io(
this.config.apiBaseUrl + "?_id=" + this.data.userID,
{
reconnectionAttempts: 3,
reconnectionDelay: 10000,
transports: ['websocket']
}
)
this.sockets.on("snippets", event => {
this.handleIncomingNotification(event.message);
})
this.sockets.on("tasks", event => {
this.handleIncomingNotification(event.message);
})
this.sockets.on("payments", event => {
this.handleIncomingNotification(event.message);
})
};
};
If you still need your current library to work - then you may need to try moving it to another suitable module that loads later in your app start life cycle when global configs and variables are already available across the application. Hope this helps.
I've begun a project using Angular5 inside a ASP.NET MVC project. I've been following the official tutorial on the Angular site, just to get my feet wet, and it's been great until now.
I've gotten to the end of the tutorial, using the Http module, but I can't get the module imported. When I add the HttpClientModule into the the imports list I get this console error:
Error: Unexpected token <
Evaluating http://localhost:54129/node_modules/#angular/common/bundles/common.umd.js/http
Evaluating http://localhost:54129/app/app.module.js
Evaluating http://localhost:54129/app/main.js
Loading app/main.js
at eval ()
at evaluate (evaluate.js:106)
at instantiate.js:394
at dynamicExecute (register-loader.js:665)
at doEvaluate (register-loader.js:612)
at ensureEvaluate (register-loader.js:520)
at register-loader.js:538
at Object.eval (:54129/app/app.module.js:12)
at eval (:54129/app/app.module.js:34)
at eval (:54129/app/app.module.js:35)
(anonymous) # localhost/:20
With some searching I found that I maybe needed to include:
'#angular/common/http': 'npm:#angular/common/bundles/common-http.umd.js',
'tslib': 'npm:tslib/tslib.js'
into my systemjs.config.js file, which I have done, but it hasn't resolved the error.
Here's my app.module.ts:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpClientModule } from '#angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AccountInfoComponent } from './AccountInfo/AccountInfoComponent';
import { VehicleComponent } from './Vehicle/VehicleComponent';
import { UserService } from './Services/UserService';
import { CustomerService } from './Services/CustomerService';
#NgModule({
imports: [BrowserModule, FormsModule, AppRoutingModule, HttpClientModule],
declarations: [AppComponent, AccountInfoComponent, VehicleComponent],
bootstrap: [AppComponent],
providers: [UserService, CustomerService]
})
export class AppModule { }
And my systemjs.config.js:
/**
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
'app': 'app',
// angular bundles
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/common/http': 'npm:#angular/common/bundles/common-http.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
// other libraries
'tslib': 'npm:tslib/tslib.js',
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
defaultExtension: 'js',
meta: {
'./*.js': {
loader: 'systemjs-angular-loader.js'
}
}
},
rxjs: {
defaultExtension: 'js'
}
}
});
})(this);
Any idea what I'm missing or what I'm doing wrong?
This error could be caused how it's being built (with, I assume, the angular CLI(. What flags are you using on ng build? Check out the file names in the angular CLI destination directory. In the dev build, the files are called "inline.bundle.js"; in the production build, cache busting is implemented, so they have funky names like "inline.d78byc79tcnuasdf.bundle.js".
Something like this should work:
ng build --prod --ec=false --oh=media
This keeps the scripts and styles in the same format as in development.
The diferent flags for prod and dev builds are discussed in the docs here: https://github.com/angular/angular-cli/wiki/build#--dev-vs---prod-builds
Note This project must be run on a device, iOS or Andriod
Background:
I had installed the native google maps plugin into my ionic 2 project using the command
$ ionic plugin add cordova-plugin-googlemaps --variable API_KEY_FOR_ANDROID="YOUR_ANDROID_API_KEY_IS_HERE" --variable API_KEY_FOR_IOS="YOUR_IOS_API_KEY_IS_HERE"
as shown in the following link: http://ionicframework.com/docs/v2/native/google-maps/
Then i'd run the command $ ionic platform add ios
and then $ ionic build ios
Everything goes as expected till this point.
When i try to display a map, i see a black screen, don't know whats missing!
Code:
/src/app/app.module.ts
import { NgModule, ErrorHandler } from '#angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
#NgModule({
declarations: [
MyApp,
HomePage
],
imports: [
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage
],
providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}
/src/app/app.component.ts
import { Component } from '#angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar, Splashscreen } from 'ionic-native';
import { HomePage } from '../pages/home/home';
import {
GoogleMap,
GoogleMapsEvent,
GoogleMapsLatLng,
CameraPosition,
GoogleMapsMarkerOptions,
GoogleMapsMarker
// GoogleMapsMapTypeId
} from 'ionic-native';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage = HomePage;
constructor(platform: Platform) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
StatusBar.styleDefault();
Splashscreen.hide();
let map = new MapPage();
map.loadMap();
});
}
}
class MapPage {
constructor() {}
// Load map only after view is initialize
ngAfterViewInit() {
this.loadMap();
}
loadMap() {
// make sure to create following structure in your view.html file
// and add a height (for example 100%) to it, else the map won't be visible
// <ion-content>
// <div #map id="map" style="height:100%;"></div>
// </ion-content>
// create a new map by passing HTMLElement
let element: HTMLElement = document.getElementById('map');
let map = new GoogleMap(element);
// create LatLng object
let ionic: GoogleMapsLatLng = new GoogleMapsLatLng(43.0741904,-89.3809802);
// create CameraPosition
let position: CameraPosition = {
target: ionic,
zoom: 18,
tilt: 30
};
// listen to MAP_READY event
map.one(GoogleMapsEvent.MAP_READY).then(() => {
// move the map's camera to position
map.moveCamera(position); // works on iOS and Android
});
// create new marker
let markerOptions: GoogleMapsMarkerOptions = {
position: ionic,
title: 'Ionic'
};
map.addMarker(markerOptions)
.then((marker: GoogleMapsMarker) => {
marker.showInfoWindow();
});
}
}
/src/pages/home/home.html
<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<div #map id="map" style="height:100%;"></div>
</ion-content>
Could someone please help in figuring out the problem. Your help is deeply appreciated.
Link to documentation
Link to project repo
let map = new MapPage();
map.loadMap();`
MapPage is a plain typescript class. It is not a component and it wont run lifecycle hooks like this:
ngAfterViewInit() {
this.loadMap();
}
Also the call map.loadMap() in App.html is not working because your element is in home component.
I suggest you move map related code to home component.
Also use viewChild to get the map div which would be an ElementRef object.
Home Component
constructor() {}
#ViewChild('map')
private mapElement: ElementRef;
// Load map only after view is initialize
ngAfterViewInit() {
this.loadMap();
}
loadMap() {
let map = new GoogleMap(this.mapElement.nativeElement);
//...etc etc
}
}
Angular Documentation Reference: https://angular.io/docs/ts/latest/guide/
In app.scss, add:
ion-app._gmaps_cdv_ .nav-decor{
background: none !important;
}
Problem: Loading map on iOS platform was not working. It was showing black screen. However the map request was updating correctly on Google console.
Solution: I had to add the following code in .scss file -
ion-app._gmaps_cdv_ .nav-decor{
display: none !important;
}
This worked and loaded map correctly.
My solution was, do not initialize the map on the constructor, initialize it on the ionViewDidLoad.
ionViewDidLoad() {
console.log('ionViewDidLoad Maps');
setTimeout(()=>{
this.loadMap();
}, 1000)
}