"ng2-CKEditor" node module is not working with typescript[Angular2] - node.js

I am trying to configure CKEditor in my angular2 application.
I am using node as my backend platform and i am using ng2-CKEditor npm module.
Below are my code in respective files.
index.html::
<html>
<head>
<title>Angular 2 QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="app/images/myblog.ico" rel="icon" type="image/x-icon" />
<link rel="stylesheet" href="app/css/app.css">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="//cdn.ckeditor.com/4.5.6/standard/ckeditor.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<!-- 3. Display the application -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
systemjs.config.ts::
/**
* System configuration for Angular 2 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/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',
'ng2-ckeditor': 'app/utils/ckeditor/ckeditor.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api',
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './js/main',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
'angular2-in-memory-web-api': {
main: './index.js',
defaultExtension: 'js'
}
}
});
})(this);
main.ts::
import {NgModule} from '#angular/core';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app.module';
import {FormsModule} from '#angular/forms';
import {CKEditorModule} from 'ng2-ckeditor';
const platform = platformBrowserDynamic();
#NgModule({
imports: [
CKEditorModule
],
declarations: [
AppModule,
],
bootstrap: [AppModule]
})
export class AppMain { }
platform.bootstrapModule(AppModule);
app.component.ts::
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
//templateUrl: 'app/templates/write-blog.html'
template: `
<ckeditor [(ngModel)]="content" debounce="500">
<p>Hello <strong>world</strong></p>
</ckeditor>
<div [innerHTML]="content"></div>`
})
export class AppComponent {
constructor(){
//this.content = '<p>Hello <strong>World !</strong></p>'
}
}
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import {FormsModule} from '#angular/forms';
import {CKEditorModule} from 'ng2-CKEditor'
import { AppComponent } from './app.component';
#NgModule({
imports: [ BrowserModule, FormsModule, CKEditorModule],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Error::
zone.js:344 Unhandled Promise rejection: Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'ckeditor'. ("
][(ngModel)]="content" debounce="500">
Hello world
"): AppComponent#1:14
'ckeditor' is not a known element:
1. If 'ckeditor' is an Angular component, then verify that it is part of this module.
2. If 'ckeditor' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '#NgModule.schema' of this component to suppress this message. ("
[ERROR ->]
Hello world
; Task: Promise.then ; Value: Error: Template parse errors:(…) Error: Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'ckeditor'. ("
][(ngModel)]="content" debounce="500">
Hello world
"): AppComponent#1:14
'ckeditor' is not a known element:
1. If 'ckeditor' is an Angular component, then verify that it is part of this module.
2. If 'ckeditor' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '#NgModule.schema' of this component to suppress this message. ("
[ERROR ->]
Hello world
http://localhost:3000/node_modules/#angular/compiler/bundles/compiler.umd.js:8530:21)
at RuntimeCompiler._compileTemplate (http://localhost:3000/node_modules/#angular/compiler/bundles/compiler.umd.js:16905:53)
at eval (http://localhost:3000/node_modules/#angular/compiler/bundles/compiler.umd.js:16828:85)
at Set.forEach (native)
at compile (http://localhost:3000/node_modules/#angular/compiler/bundles/compiler.umd.js:16828:49)
at ZoneDelegate.invoke (http://localhost:3000/node_modules/zone.js/dist/zone.js:192:28)
at Zone.run (http://localhost:3000/node_modules/zone.js/dist/zone.js:85:43)
at http://localhost:3000/node_modules/zone.js/dist/zone.js:451:57
at ZoneDelegate.invokeTask (http://localhost:3000/node_modules/zone.js/dist/zone.js:225:37)
at Zone.runTask (http://localhost:3000/node_modules/zone.js/dist/zone.js:125:47)consoleError # zone.js:344_loop_1 # zone.js:371drainMicroTaskQueue # zone.js:375ZoneTask.invoke # zone.js:297
zone.js:346 Error: Uncaught (in promise): Error: Template parse errors:(…)consoleError # zone.js:346_loop_1 # zone.js:371drainMicroTaskQueue # zone.js:375ZoneTask.invoke # zone.js:297
As i am new to angular2 with typescript and basically for MEAN stack, please help.
I check other post for the same issue but did not help to resolve my issue.

You need to add FormsModule to your module's imports in order to use ngModel directive because it is part of FormsModule:
#NgModule({
imports: [
CKEditorModule,
FormsModule
]
Your code is also very messy, you should check out official Angular 2 quickstart app to see how your code should be structured.

Related

Using Mocked Service Worker (msw) with #web/test-runner

I am trying to setup msw with #web/test-runner (and playwright). The problem is that I don't know how the mockServiceWorker.js can be picked up by the test runner (which uses browser, not nodejs like jest). There is an example with karma:
https://github.com/mswjs/examples/tree/master/examples/with-karma, probably I have to do something similar but I have no idea where to start. Any hints are welcome.
I am not sure if it is important, but let me share my web.test-runner.config.js
import vite from 'vite-web-test-runner-plugin'
import { playwrightLauncher } from '#web/test-runner-playwright';
export default {
plugins: [ vite() ],
coverageConfig: {
include: [ 'src/**/*.{svelte,js,jsx,ts,tsx}' ]
},
browsers: [
playwrightLauncher({ product: 'chromium' })
],
testRunnerHtml: testFramework => `
<!DOCTYPE html>
<html>
<head>
<script type="module">
window.global = window;
window.process = { env: {} };
</script>
<script type="module" src="${testFramework}"></script>
</head>
</html>
};
and my test command
"test": "web-test-runner \"test/**/*.test.ts\"",

migrating to material design with angular5

I am developing an angular4 app with bootstrap.
I just moved to angular5 and I wonder if is not the case to use material design for components instead of prime-ng ng-bootrap kendo-ui etc...
Thanks
In console:
ng new pjt
cd pjt
npm install #angular/material #angular/cdk --save
npm install #angular/animations --save
Create app/modules/material.module.ts file and include:
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { MatButtonModule } from '#angular/material';
#NgModule({
imports: [MatButtonModule],
exports: [MatButtonModule],
})
export class MaterialModule { }
Note each element Mat...Module you want to use needs to be added in the above file comma separated to the import, imports and exports lines.
update app/app.modules.ts to include
import { BrowserAnimationsModule} from '#angular/platform-browser/animations';
import { MaterialModule } from './modules/material.module';
...
imports: [
...
BrowserAnimationsModule,
MaterialModule
],
update styles.scss to include
#import "~#angular/material/prebuilt-themes/indigo-pink.css";
In console
npm install hammerjs --save
update main.ts to include
import 'hammerjs';
update index.html to include
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
In console
ng serve
Then you can start including in your components the material elements, e.g. <button mat-button>Some Btn<button>
... check out material.angular.io for elements ...
then check out https://coursetro.com/posts/code/113/How-to-Build-an-Angular-5-Material-App for more details.

Parsing XML in typescript

Using Typescript 2.0 (tsc version 2.0.3).
I have unsuccessfully attempted to use the xml2js node library inside an angular2/typescript application (see https://www.npmjs.com/package/xml2js). Seems clear I am not familiar enough with the way the SystemJS sets up the library for consumption.
To install the xml2js library I did the following:
npm install --save xml2js
npm install --save #types/xml2js
Here are the relevant files:
tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false,
"outDir" : "build"
}
}
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: 'build',
// 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',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
'lodash' : 'npm:lodash',
'xml2js' : 'npm:xml2js'
},
// 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'
},
lodash: {
main : 'index.js',
defaultExtension: 'js'
},
xml2js: {
defaultExtension: 'js'
}
}
});
})(this);
The consuming file:
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/Rx';
import * as _ from 'lodash';
import * as xml2js from 'xml2js';
#Injectable()
export class CatalogService {
constructor (private http:Http) {
}
getCatalog() {
//return Promise.resolve(['This', 'That']);
var xml = "<root>Hello xml2js!</root>"
xml2js.parseString(xml, function (err, result) {
alert(result);
});
alert(_.indexOf([1, 2, 1, 2], 2));
}
}
index.html file
<html>
<head>
<title>Angular QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- 1. Load libraries -->
<!-- Polyfill for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<!-- 3. Display the application -->
<body>
<dsa-app>Loading DSA App...</dsa-app>
</body>
</html>
With that setup, I do get an error as follows:
zone.js:1382 GET http://localhost:3000/node_modules/xml2js/ 404 (Not Found)
The lodash library loads fine, so I am pretty sure the issue here has to do with the way the xml2js library is defined more than my setup.
Closest solution I have seen for this is a bit dated for Angular 2.0, but I put it here for reference: Use JS library xml2js with Angular 2
Although the question specifically addresses using that library, any other ideas on how to parse/convert xml into something manageable inside TypeScript would also come in handy.
Update:
As suggested I started adding "main" definitions to my systemjs configuration. However, I though part of this was that the dependencies would be loaded/figured out from the node content.
Thus modifying the system.config.js to have:
xml2js: {
main: 'lib/xml2js.js',
defaultExtension: 'js'
},
Move the issue to where now I get 404 entries for sax and xmlbuilder.
Thus, I added the following too:
sax: {
main: 'lib/sax.js',
defaultExtension: 'js'
},
xmlbuilder: {
main: 'lib/index.js',
defaultExtension: 'js'
}
Which address the sax and xmlbuilder, but then more errors popup.
I thought the whole idea with using the SystemJS and the tsconfig would be that these would be figured out from the node modules, adding all the tree dependencies on the packages seems to defeat the purpose.
I think the issue here is in your systemjs config - you haven't defined main for xml2js. Because of that systemjs doesn't know which file to load, so tries to load the NPM directory directly for some reason (loading /node_modules/xml2js as a file, which clearly isn't going to work). Note that your lodash config does specify 'index.js', presumably leading to /node_modules/lodash/index.js being loaded when you import lodash, which is why that works.
If you specify a 'main' for xml2js in your systemjs config that pointing to lib/xml2js.js then systemjs should be able to find it correctly.
As noted by #tim-perry, the issue here was the way the package was defined.
A further issue in my work is that I was making wrong assumptions about what SystemJS would do for me. I need to look into a different tool (starting with JSPM) that would do the tree walk when loading the base module. In my example, lodash was working because it is self contained. However, xml2js had a lot of dependencies, that had a lot of dependencies, that had a lot of dependencies ... thus applying the solution of adding the package definition for each dependency took care of the issue albeit in a very cumbersome way.
Again, thanks to #tim-perry and #artem who helped with this.

Import node module to typescript/systemjs

I am trying to use the react blueprint library, so I npm install it and then I tried to import it like:
import { Spinner } from "#blueprintjs/core"
I am getting system.src.js:1051 GET http://localhost:8888/#blueprintjs/core 404 (Not Found)
I thought that it has to do with the typings and since there is a tsfile on the module I tried
/// <reference path="../node_modules/#blueprintjs/core/dist/index.d.ts" />
or
/// <reference path="node_modules/#blueprintjs/core/dist/index.d.ts" />
I am still getting the same error. I am new to Typescript, how can I consume a node module like this?
You need to configure SystemJS so it can find and load all necessary modules in the browser. See this answer for general explanation. Here is complete minimal example that creates blueprint spinner:
install prerequisites
npm i #blueprintjs/core
npm i react
npm i react-dom
npm i react-addons-css-transition-group
npm i #types/react
npm i #types/react-dom
npm i #types/dom4
npm i typescript
npm i systemjs
example code in test.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Spinner } from "#blueprintjs/core";
const mySpinner = <Spinner/>;
ReactDOM.render(mySpinner, document.body);
example web page
<!doctype html>
<html>
<head>
<link href="node_modules/#blueprintjs/core/dist/blueprint.css" rel="stylesheet" />
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script>
window.process = { env: {}};
System.config({
map: {
'react': 'node_modules/react',
'react-dom': 'node_modules/react-dom',
'react-addons-css-transition-group': 'node_modules/react-addons-css-transition-group/index.js',
'fbjs': 'node_modules/fbjs',
'tether': 'node_modules/tether/dist/js/tether.js',
'dom4': 'node_modules/dom4/build/dom4.max.js',
'#blueprintjs/core': 'node_modules/#blueprintjs/core/dist',
'classnames': 'node_modules/classnames/index.js',
'object-assign': 'node_modules/object-assign/index.js',
'pure-render-decorator': 'node_modules/pure-render-decorator/index.js'
},
packages: {
'react': { main: 'lib/React.js' },
'react-dom': { main: 'lib/ReactDOM.js' },
'fbjs': {},
'#blueprintjs/core': { main: 'index.js' },
'#blueprintjs/core/common': { main: 'index.js' },
'#blueprintjs/core/components': { main: 'index.js' }
}
});
System.import('./test.js').then(function(t) {
}).catch(function(e) {
console.error(e);
});
</script>
</head>
<body>
</body>
</html>
Note: It looks like SystemJS is unable to load react and react-dom using their bundles provided in node_modules/react/dist/react.js and node_modules/react-dom/dist/react-dom.js. It can however load everything from individual source files from node_modules/react/lib and node_modules/react-dom/lib, provided that you define process variable in the browser.

AngularJS2 : Getting 404 Not Found in the models folder even though file is there

I have the following app structure:
I want my application where each page like "Create.cshtml" will
bootstrap(Scripts/app/project/create/app.projects.create-boot.ts)
and
load the application (/app.projects.create.ts).
I also have a models folder which will hold all my models and will be shared.
serviceline.js(Scripts/models/serviceline.ts)
app.projects.create-boot.ts:
/// <reference path="../../../../node_modules/angular2/typings/browser.d.ts" />
import {bootstrap} from 'angular2/platform/browser'
import {AppProjectsCreateComponent} from './app.projects.create'
import {ServiceLine} from '../../../models/serviceline';
bootstrap(AppProjectsCreateComponent, [ServiceLine]);
app.projects.create.ts:
import {Component} from 'angular2/core';
import {ServiceLine} from '../../../models/serviceline';
#Component({
selector: 'project-create',
templateUrl: '../../appScripts/app/projects/create/app.projects.create.html'
})
export class AppProjectsCreateComponent {
name = "max";
serviceLines: ServiceLine[];
constructor() {
//this.serviceLines = [ new ServiceLine(1, "Name Test") ];
}
}
serviceLine.ts
export class ServiceLine {
ServiceLineId: number;
Name: string
constructor(serviceLineId: number, name: string) {
this.ServiceLineId = serviceLineId;
this.Name = name;
}
}
Create.cshtml:
#*
For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
*#
#section head{
<script src="~/lib/es6-shim.min.js"></script>
<script src="~/lib/system-polyfills.js"></script>
<script src="~/lib/shims_for_IE.js"></script>
<script src="~/lib/angular2-polyfills.js"></script>
<script src="~/lib/system.js"></script>
<script src="~/lib/rx.js"></script>
<script src="~/lib/angular2.dev.js"></script>
<!-- 2. Configure SystemJS -->
}
#{
<script>
System.config({
map: {
appScripts: '../appScripts/app/projects/create'
},
packages: {
appScripts: {
defaultExtension: 'js'
}
}
});
System.import('appScripts/app.projects.create-boot')
.then(null, console.error.bind(console));
</script>
}
<br />
<project-create></project-create>
Everything was loading find until I added ServiceLine[] in the app.projects.create.ts file.
Here is the error:
What am I missing? Why can't Angular find the serviceLine.js.
Edit: Change the map field.
<script>
System.config({
map: {
appScripts: '../appScripts' //Change Here
},
packages: {
appScripts: {
defaultExtension: 'js'
}
}
});
System.import('appScripts/app/projects/create/app.projects.create-boot') //Change Here
.then(null, console.error.bind(console));
</script>
The problem is that your service file isn't targetted with your SystemJS configuration because of the map block.
So SystemJS doesn't append the JS extension. I would remove the map block:
<script>
System.config({
/* map: {
appScripts: '../appScripts/app/projects/create'
}, */
packages: {
appScripts: {
defaultExtension: 'js'
}
}
});
System.import('appScripts/app/projects/create/app.projects.create-boot')
.then(null, console.error.bind(console));
</script>
and update accordingly the path in your imports.
With this configuration the "model" will be token into account. Your configuration would only work if your "model" folder was under the "create" one.

Resources