I am trying to convert angular components to angular web component, I followed few articles to do it which is good, but when I tried to convert angular directive as web component it throws some error which I am not able to figure out what is wrong I am doing, also I don't have any idea on can we convert an angular directive to angular web component. Below is code which I tried to convert directive as web component.
Tooltip Directive:
<pre>#directive({
selector: '[tooltip]'
})
export class TooltipDirective {
constructor(private el: ElementRef) {
this.el.nativeElement.classList.add('my-tooltip');
}
}</pre>
Creation of tooltip web components snippet:
<pre>export class AppModule implements DoBootstrap {
constructor(private injector: Injector) {}
ngDoBootstrap() {
const webTooltip = createCustomElement(TooltipDirective, {
injector: this.injector,
});
customElements.define("web-tooltip", webTooltip);
}
}
</pre>
How I am trying to use in app HTML file is below code
Web tooltip selector:
<span web-tooltip id="tooltip" content="This is a tooltip.">
enter image description here
If I try to write same code for any component its working fine but for directive as I shown code above its not working.
Related
I have an angularjs 1.7 component which I need to upgrade to angular 8 component. It has an external script, which I cannot modify. That script inserts an iframe into the div and it expects some settings from the component to customize the iframe.
The old component code:
angular.module('myApp.shared').component("userExternal", {
template: '<div id="userIframe"></div>',
controller: function ($window) {
this.scriptUrl = "//myurl/widget/addIframe.js";
this.$onInit = function () {
$window.UserSettings = [];
$window.UserSettings.push(['set', {
btn_color: '#008A00',
bg_color: 'white'
}]);
});
};
}
});
I have two problems here:
I don't know how to convert $widnow to angular 8 window object.
When I convert $window to angular 8 window, how can I add UserSettings array to it?
This is my angular 8 component, but my code did not work correctly.
HTML Template
<script src="//myurl/widget/addIframe.js"></script>
<div class="user_external></div>
TS Code
import { Component} from '#angular/core';
#Component({
selector: 'app-user',
templateUrl: './user-external.component.html'
})
export class UserExternalComponent {
constructor() {
}
ngOnInit() {
window.UserSettings = [];
window.UserSettings.push(['set', {
btn_color: '#008A00',
bg_color: 'white'
}]);
console.log(window);
}
}
Thank you
Following a combination of this tutorial for the window reference and this tutorial for upgrading from AngularJS to Angular in general, I created an injectable service that seems to be doing the job, at least so far in a downgraded context. (Next step is to start upgrading the modules that use the dependency, but I successfully replaced all AngularJS injections of $window with my new APIWindow class, and everything works as before with no breaking errors.)
Keeping in mind this is being used as a downgraded Angular class inside a currently mostly AngularJS app, the class looks like this:
// api.window.service.ts
import { Injectable } from '#angular/core'
import { downgradeInjectable } from '#angular/upgrade/static'
import * as angular from 'angular'
// You could change this to return any property on Window, but external is the one I use:
function _external (): any {
return window.external
}
#Injectable()
export class APIWindow {
get external (): any {
return _external()
}
}
angular
.module('APIModule')
.service('APIWindow', downgradeInjectable(APIWindow))
Hopefully this helps someone else with a similar situation following this upgrade path!
I am running UI Router with angular 4.x. Below code is not rendering anything and I did not get any error message too. But when I changed to $default as a view name, then I am getting the page.Please suggest me.
<app-root>
<ui-view name='main'></ui-view>
</app-root>
Below is the angular State Definition,
export const appState = {
name: 'app',
views : {
main : {
component: AppComponent
}
}
};
When Angular application bootstrap's, it wipes out the inner content of app-root(root) component. What ever you put inside root component will appear until Angular application bootstrap. Generally this place has been used to add Splash screen, loader to show initial loading.
To see your ui-view to replace via ui-router configuration, you should add ui-view inside app-root component HTML.
#Component({
selector: 'app-root',
template: `<ui-view name='main'></ui-view>`
})
export AppRootComponent {
}
I have a hybrid angular-cli that roughly follows Victor Savkin's Lazy Loaded AngularJS guide. AngularJS is bootstraped in the constructor of a LazyLoaded Angular module. The main difference between my app and the guide is that I am trying to wrap the <ui-view> directive inside of some Angular components. Because of how my layout is structured the <ui-view> element will not be available when AngularJS is bootstrapped and may be added or removed at any time.
import { Component, Directive, ElementRef, Injector } from '#angular/core';
import { UpgradeComponent } from '#angular/upgrade/static';
import * as angular from 'angular';
#Component({
template: `
<layout-wrapper>
<my-toolbar></my-toolbar>
<layout-contents>
<ng2-ui-view>
<h3 class="text-center">AngularJS page not loaded</h3>
</ng2-ui-view>
</layout-contents>
</layout-wrapper>
`,
})
export class LegacyOutputComponent { }
#Directive({selector: 'ng2-ui-view'})
export class UpgradedUiViewComponent extends UpgradeComponent {
constructor(ref: ElementRef, inj: Injector) {
super('uiViewWrapper', ref, inj);
}
}
export const routerPatchModule = 'arcs.router.patch';
// We need to define a wrapper for ui-view because we can only upgrade
// components with only one definition. uiView cannot be automatically
// upgraded because its definition is too complex
angular.module(routerPatchModule, ['ui.router'])
.component('uiViewWrapper', { template: '<ui-view></ui-view>'})
When I run the code a Error: No provider for $scope! error is thrown. Checking the stack trace I can see that it is thrown in the UpgradeComponent super class. The injector tries to get $scope and
Alternative is to let Angular know that it needs to provide the $scope.
import { Injector } from '#angular/core';
// allow $scope to be provided to ng1
export const ScopeProvider = {
deps: ['$injector'],
provide: '$scope',
useFactory: (injector: Injector) => injector.get('$rootScope').$new(),
};
#Directive({
providers: [ ScopeProvider ],
selector: 'ng2-ui-view',
})
export class UpgradedUiViewComponent extends UpgradeComponent {
constructor(ref: ElementRef, inj: Injector) {
super('uiViewWrapper', ref, inj);
}
}
This setup will not work. AngularJS needs to be able to load in the root of your application in order for the scope to be defined correctly.
A better way to approach this problem is to use the <div ui-view> directive in the root of your application (as in the upgrade guide) and then to downgrade a layout component from Angular into AngularJS to wrap your content.
I am using TypeScript with AngularJS 1.5.x and in my tsconfig it all gets compiled down into SystemJS code. Now the issue I am having is only in controller classes that have an import at the top (see example below). If I take these imports out everything works just fine and the controller is found, but if I put them in, the controller is wrapped in a System.register block and it is not found when I go to my view.
I'm a beginner with SystemJS so I'm hoping I am just doing something really dumb, but it has been driving me nuts as to why when I have the imports it does not work.
import { testService} from '../services/test.service';
import { testClass} from '../models/testClass';
namespace app.controllers {
export class testController{
private testService: any;
constructor(public $http: angular.IHttpService) {
}
getData(): any {
}
}
angular.module('app')
.controller('testController', testController);
}
Following this question and resolution:
AngularJS directive not displaying the template
I wanted to try the same with an angular component and typescript, but i can't seem to get it working. The component just doesn't show.
My html looks like this:
<div ng-app="SuperHero">
<super-man></super-man>
</div>
My Typescript looks like this:
module Application.Components {
export class superMan implements ng.IComponentOptions {
template: string = "<h1>Hello from component</h1>";
}
}
var appModule = angular.module("SuperHero", []);
appModule.component("superMan", () => Application.Components.superMan);
A fiddle here: http://jsfiddle.net/589301uo/2/
Component definition takes configuration object, not a function. So in your example you should use new Application.Components.superMan() instead of () => Application.Components.superMan.
Also pay attention that components were added in angular 1.5 and your fiddle uses older version.
Here's working demo.