Integrate xterm.js to Angular - javascript

I'm new to Angular.
I'm trying to use xterm.js (https://xtermjs.org/) but it display badly.
Here is the render :
Render
I created a xterm component. The xterm.component.ts file code is :
import { Component, OnInit } from '#angular/core';
import { Terminal } from "xterm";
#Component({
selector: 'app-xterm',
templateUrl: './xterm.component.html',
styleUrls: ['./xterm.component.css'],
})
export class XtermComponent implements OnInit {
public term: Terminal;
container: HTMLElement;
constructor() { }
ngOnInit() {
this.term = new Terminal();
this.container = document.getElementById('terminal');
this.term.open(this.container);
this.term.writeln('Welcome to xterm.js');
}
}
My xterm.component.html only contains this :
<div id="terminal"></div>
I don't really know what to do more ...
Thanks in advance guys

You must set the component encapsulation
#Component({
encapsulation: ViewEncapsulation.None,
...
})

Encountered the same problem and found this page.
Maybe this is too late for the OP, but could be useful for others.
The styles are wrong because 1) the xterm.css is not loaded, and 2) the encapsulation.
My solution to 1) was to add #import 'xterm/dist/xterm.css'; in the scss file for this component.
And 2) can be solved by setting encapsulation: ViewEncapsulation.None as Victor96's answer, or better setting encapsulation: ViewEncapsulation.ShadowDom.
Hope this helps.

I know this is old, but I had to put terminal initialation in ngAfterViewInit. Otherwise the DOM elements are undefined.

Try to use in template reference variable by using the hash symbol
<div #myTerminal></div>
and in component
#ViewChild('myTerminal') terminalDiv: ElementRef;
In ngOnInit
ngOnInit() {
this.term = new Terminal();
this.term.open(this.terminalDiv.nativeElement);
this.term.writeln('Welcome to xterm.js');
}

Related

Angular functions are performed twice when called in the html file

I tried to start an angular project, I've created a simple component and started a console.log in it but I have Confusing problem. when I calling a function in html file from ts file its run twice
TS:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-hello',
templateUrl: './hello.component.html',
styleUrls: ['./hello.component.less']
})
export class HelloComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
log(val)
{
console.log(val);
}
test() {
let time = new Date()
console.log(time.getSeconds());
}
}
html :
hello works!
{{log('test')}}
{{test()}}
image log:
enter image description here
Where and how often do you call your component?
Can you produce a simple example on stackblitz?
Without any further info, we can just guess what it is.
You propably have called your component via '' twice.
Each instance will call all your template and hence its calling functions.

Access text (not instance of another component) with ContentChild

How can I access a string of text given within the tags of a component
<my-custom-component>THIS TEXT</my-custom-component>
Within a template, I can use ng-content, or if it is an instance of some other class I can access it within the component definition like demonstrated in these examples. However I am interested in detecting if there is a string of text there or not, which I believe would make providedText undefined. However, I am always getting undefined.
#ContentChild(Element, { static: true }) providedText: Text | undefined;
I have tried Text as the first element passed to #ContentChild. Passing any will not work (I don't know why).
StackBlitz
I am interested mostly in finding if there is a string or undefined, but am also curious why ContentChild(Text... isn't working.
Edit:
I have added a potential solution, but it seems pretty imperfect, so I hope something better comes along.
Edit 2:
I now understand that #ContentChild is not a mechanism for selecting whatever native HTML I want without wiring it up to Angular’s dependency graph with a ref, directive, etc.
I am still curious if my proposed solution below is a bad idea for any reason.
My solution for now (since I wish to capture all transcluded content) is to wrap ng-content in a containing element, then get its innerText.
#Component({
selector: "app-parent",
template: `
<span #transcludedContainerRef>
<ng-content></ng-content>
</span>
`
})
export class ParentComponent implements AfterViewInit {
#ViewChild("transcludedContainerRef", { static: false })
transcludedContainerRef: ElementRef | undefined;
buttonText: string;
ngAfterViewInit() {
const isButtonTextPresent = this.transcludedContainerRef.nativeElement
.innerText;
if (isButtonTextPresent) {
console.log(isButtonTextPresent); // successfully logs content
}else {
console.log('No text set');
}
}
}
It does feel hacky, but it works. I am holding out for something better.
it's difficult if I don't know about your <my-custom-component>
In general if your custom component it's only
<ng-content></ng-content>
You can inject in constructor the elementRef
constructor(public el:ElementRef){}
From a parent
<hello >
Start editing to see some magic happen :)
</hello>
You can use
#ViewChild(HelloComponent,{static:false}) helloComponent:HelloComponent
click()
{
console.log(this.helloComponent.el.nativeElement.innerHTML)
}
If your component has any variable -or ViewContent-, you can access this variables in a similar way
So the other way to read the inner text from the component is that child component emit the value whatever it get's as input from other component. See below:
hello.component.ts
import { Component, Input, Output, EventEmitter, OnInit } from '#angular/core';
#Component({
selector: 'hello',
template: `<h1>Hello {{name}}!</h1>`,
styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent implements OnInit {
#Input() name: string;
#Output() innerText: EventEmitter<string> = new EventEmitter();
ngOnInit() {
this.innerText.emit(this.name);
}
}
app.component.ts
import { Component, ContentChild, AfterContentInit, OnInit } from "#angular/core";
#Component({
selector: "app-parent",
template: "content from <code>app-parent</code>"
})
export class ParentComponent implements AfterContentInit {
#ContentChild(Element, { static: true }) providedText: Text | undefined;
ngAfterContentInit() {
console.log("ngAfterContentInit Content text: ", this.providedText);
}
}
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "Angular";
_innerText: string;
ngAfterContentInit() {}
get childContent(): string {
return this._innerText;
}
set childContent(text) {
this._innerText = text;
}
innerTextFn(innertext: string) {
this.childContent = innertext;
console.log('Event: ', innertext);
}
}
app.component.html
<hello name="{{ name }}" (innerText)="innerTextFn($event)"></hello>
<app-parent>This is the content text</app-parent>
Here is stackblitz url to check: https://stackblitz.com/edit/angular-bacizp
I hope this may helpful for you and if yes then accept this as correct answer.

Javascript Angular 4 using eventEmitter though several layers of components

I am having a bit of a problem with getting the following situation done in Angular.
I am using Angular 4 and this is the situation.
app.component.html contains a wrapper div which I would like to be able to change it's color by adding a class to it.
My problem is that I have different layers of components.
For example, if I wanted to change the class in app.component.html it would have this:
app.component - root
button-wrapper.component - holds the button
button.component - message comes from there.
Normally I could do this:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'app';
myClass = '';
handleEvent(value) {
console.log(value);
myClass = value;
}
}
and in app.component.html have this:
<div [ngClass]="myClass">
<app-button (outputEvent)="handleEvent($event)"></app-button>
</div>
BUT, my problem is that app-button component is inside button-wrapper component so it looks like this:
<div [ngClass]="myClass">
<button-wrapper></div>
</div>
So where would I put this:
(outputEvent)="handleEvent($event)"
How can I go round this issue?
You can chain events as long as their direct children:
button.component.ts (selector: app-button)
startChainEvent() {
this.outputEvent.emit('className');
}
button-wrapper.component.html
<app-button (outputEvent)="handleEvent($event)"></app-button>
button-wrapper.component.ts (selector: app-button-wrapper)
handleEvent(e) {
this.outputEvent.emit(e);
}
app.component.html
<app-button-wrapper (outputEvent)="handleEvent($event)"></app-button-wrapper>
app.component.ts
handleEvent(e) {
myClass = e;
}

How to call one method from another method in same Angular (Typescript) Component Class?

I am seeing a strange error where I try to call a method from another method and both method are in the same Angular 2 TypeScript component.
See in the below code that when ngOnInit() is invoked, it kicks off method1. method1 tries to invoke this.method2() . This is where the issue lies.
The error that appears is the following:
Error: Cannot read property 'method2' of undefined
Why is the this object undefined? How can I get around this so that I can call methods belonging to a class from other methods in the same class as I would, say in a language like Java?
import {Component, OnInit} from '#angular/core';
#Component({
selector: 'my-dashboard',
moduleId: module.id,
templateUrl: './dashboard.component.html',
styleUrls: [ './dashboard.component.css' ]
})
export class DashboardComponent implements OnInit {
constructor() {
}
ngOnInit(): void {
this.method1();
};
method1(): void {
this.method2();
};
method2(]): void {
console.log("hi");
}
}
I copied your exact code in this Plunker (but removed the unusual ']' from method2's argument) and it's working fine. I have added a button as well, to invoke Method1() as many times you want.
My suggestion is, remove moduleId: module.id from your component metadata and try again. Even the Plunker doesn't work when its in there.
UPDATE:
"All mention of moduleId removed. "Component relative paths" cookbook deleted (2017-03-13)" - https://angular.io/docs/ts/latest/guide/change-log.html
app.ts:
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<button (click)="method1()">Invoke Method 1</button>
</div>
`,
})
export class App implements OnInit{
name:string;
constructor() {
this.name = `Angular! v${VERSION.full}`
}
ngOnInit(): void {
this.method1();
};
method1(): void {
this.method2();
};
method2(): void {
alert("hi");
}
}
This isn't runnable so I can't test this solution myself, but try renaming the function to "this.method2" rather than just "method2".

Angular 2 Directive for a component overrides ng-content?

I have a Component that is called ButtonComponent:
import { Component } from "angular2/core";
#Component({
selector: 'btn',
template: '<div class="btn"><ng-content></ng-content></div>'
})
export class ButtonComponent { }
and Directive:
import { Directive, Input } from 'angular2/core';
#Directive({
selector: 'btn[dialog-data]'
})
export class DialogButtonDirective {
#Input('dialog-data')
public dialogData: any;
}
But if I try to use it like this:
<btn [dialog-data]="dart()">DART</btn>
Then button have nothing inside of it.
Why? When I'm not using this directive everything's fine.
OK, it's a bit confusing but I found the answer. This code isn't working because DialogButtonDirective declared in 'directives' field before ButtonComponent.
So I've changed this:
directives: [DialogButtonDirective, ButtonComponent]
To this:
directives: [ButtonComponent, DialogButtonDirective]
And it solved the problem. Thanks!

Categories