Best practice for replacing ng-include when upgrading from angularjs to angular? - angularjs

To my dismay angular no longer supports the ng-include directive. My code base uses hundreds of shared partial html files. I cant seem to find any documentation. Can anyone point meet in the right direction. Is the best practice just to componentize every html file?

You can use ngTemplateOutlet directive as an alternative to ng-include in angular by passing a TemplateRef. Here I mentioned a sample code to do it.
#Component({
selector: 'child',
template: `
<div>
child template which includes myTemplate
<ng-container [ngTemplateOutlet]="myTemplate"></ng-container>
</div>`
})
export class ChildComponent {
#Input() myTemplate: TemplateRef<any>;
}
#Component({
selector: 'app-root',
template: `
<p>Parent</p>
<child [myTemplate]="myTemplate"></child>
<ng-template #myTemplate>hi julia template!</ng-template>
`
})
export class AppComponent {
#ViewChild('myTemplate', {read: TemplateRef}) myTemplate: TemplateRef<any>;
}

Related

Angular UpgradeModule cannot downgrade #Directive

I am trying to work around not being able to downgrade an Angular 8 #Directive using UpgradeModule.
I have a nested angular material component that needs to hook into cdkScrollable. My hierarchy look likes this:
<div class="some-class-that-allows-scroll"> <-- angularjs scrollable component
<mat-form-field></mat-form-field> <-- angular 8 component that needs cdkScrollable on parent
There is no way to downgrade the cdkScrollable directive to work in angularjs, IE
<div cdkScrollable class="some-class-that-allows-scroll"> <-- Will not work in angularjs template
<mat-form-field></mat-form-field>
Since I cannot downgrade the cdkScrollable #directive I was trying to "wrap" that directive in a reusable angular 8 component, and then downgrade that component.
IE:
Angular 8 component:
import { Component } from '#angular/core';
#Component({
selector: 'scroll-wrapper',
templateUrl: './scroll.component.html',
styleUrls: ['./scroll.component.scss']
})
export class ScrollWrapperComponent {
constructor() { }
}
Template:
<div cdkScrollable>
<ng-content></ng-content>
</div>
When using that downgraded component in angularjs template:
<scroll-wrapper>
<div class="some-class-that-allows-scroll"> <-- angularjs scrollable component
<mat-form-field></mat-form-field> <-- angular 8 component that needs cdkScrollable on parent
</div>
</scroll-wrapper>
However when doing this the scrollable class and the cdkScrollable directive do not end up on the same element. Is there a way to create an angular 8 component that wraps another component and have the cdkScrollable directive applied to the same element that is being wrapped?

clr-checkbox dynamic set of checkboxes with different colors AngularJs

I am following the https://vmware.github.io/clarity/documentation/v0.13/checkboxes and need to use different colors when the checkbox is checked.
Code HTML:
<div class="form-group">
<label>With a list of objects</label>
<clr-checkbox *ngFor="let item of items$"
[(clrChecked)]="item.running"
[clrDisabled]="item.disabled">
{{ item.name }}
</clr-checkbox>
</div>
Code Controller:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-checkboxgroup',
templateUrl: './checkboxgroup.component.html',
styleUrls: ['./checkboxgroup.component.scss']
})
export class CheckboxgroupComponent implements OnInit {
items$: Object;
constructor() { }
ngOnInit() {
this.items$ = [{id:1,name:'Custom',color:'cyan'},
{id:2,name:'Primary',color:'green',running:false,disabled:false},
{id:3,name:'Info',color:'blue',running:false,disabled:false},
{id:4,name:'Warning',color:'yellow',running:false,disabled:false},
{id:5,name:'Danger',color:'red',running:false,disabled:false}];
}
}
You can achieve that with the help of the currentColor keyword in CSS and a slight change of the default Clarity checkbox template. The template would look as follows:
<clr-checkbox *ngFor="let item of items$" [style.color]="item.color" [(clrChecked)]="item.running" [clrDisabled]="item.disabled">
<span class="checkbox-label">{{ item.name }}</span>
</clr-checkbox>
Then apply the following CSS in your component CSS.
.checkbox-label {
color: #000;
}
clr-checkbox ::ng-deep input[type=checkbox]:checked+label::before {
background-color: currentColor;
}
You can see that I used style binding on the clr-checkbox's color property. Hence, the color of a checked checkbox will inherit that color through currentColor.
Btw, if you add the above CSS snippet in your global style file instead of a component style, you don't need that ::ng-deep.
Here is the working sample:
https://stackblitz.com/edit/clr-checkbox-checkbox-multi-color

AngularJS: Use variable inside component

I want to use an input variable and display it inside my component HTML but I can't get it to work.
I'm pretty sure I miss something important here but can't say what.
Here is my component declaration:
app.component('requestSummary', {
templateUrl: "./Template/request-summary",
controller: function RequestSummary() {
var vm = this;
},
bindings: {
request: "="
}
});
The component template:
<div>
<h1>{{ vm.request.Pnr }}</h1>
</div>
(I have also tried without the vm)
The component use:
<md-card ng-repeat="request in vm.requests">
<md-card-content>
<request-summary request="request"></request-summary>
</md-card-content>
</md-card>
When I do a console.log(vm) inside the component controller, I can see my request is there:
But I don't know how to print it inside the HTML.
Any help is appreciated.
Components have an automatic default controllerAs controller with an alias of $ctrl. You need to use:
<div>
<h1>{{ $ctrl.request.Pnr }}</h1>
</div>
And you can get rid of the var vm = this;.

Can a CSS class selector be applied to a component?

I have the following Plunker that uses ui-router and Angular's 1.6x new component feature.
The state 'userRegister' becomes active then initialises the 'userRegister' component. This component injects a new <user-register/> into the <ui-view> then injects the HTML contents of the ng-template script block, which is all working fine.
The final DOM ends up being:
<ui-view class="ng-scope">
<user-register class="ng-scope ng-isolate-scope">
<h1 class="header">Create account</h1>
</user-register>
</ui-view>
However, I cannot find a way to add a CSS class selector to the <user-register/> tag.
e.g. using a class selector called .example I'd like to achieve the following:
<user-register class="example ng-scope ng-isolate-scope">...<user-register/>
Any ideas please?
Sure you could always wrap the template on a div and put the class there.
If don't want to do it, you can inject the $element and use the $postLink function to add the class you need:
.component('userRegister', {
templateUrl: '/views/user-register',
controller: function($element) {
this.$postLink = function() {
$element.addClass('example');
}
}
})
Here is the working plunker:
https://plnkr.co/edit/VuWu8L9VqrgJRGnxItY2?p=preview
Final DOM:
<user-register class="ng-scope ng-isolate-scope example">
<h1 class="header">Create account</h1>
</user-register>

why row is not render in angular 2?

I am trying to send data from one component to another using input attr.
but I am getting this error
VM575 zone.js#0.6.17?main=browser:484 Unhandled Promise rejection: Template parse errors:
Can't bind to 't' since it isn't a known property of 'row-item'.
1. If 'row-item' is an Angular component and it has 't' input, then verify that it is part of this module.
2. If 'row-item' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '#NgModule.schema' of this component to suppress this message.
(" <ul>
<li *ngFor="let tt of todoService.todos">
<row-item [ERROR ->][t]='tt'></row-item>
</li>
I added this in my demo
import {Component, Input} from "#angular/core";
#Component({
selector:'row-item',
template :`<div>
<span>{{t}}</span>
</div>`
})
export class TodoRow{
#Input t;
}
used like this
#Component({
selector: 'todo-list',
template: `<div>
<ul>
<li *ngFor="let tt of todoService.todos">
<row-item [t]='tt'></row-item>
</li>
</ul>
</div>`
})
here is my code
http://plnkr.co/edit/WXgdKF2gx9Kpj7eqmDJv?p=preview
Your declaration should be something like this:
#Input() t;
You forgot to add () while defining you input for the component.
import {Input} from '#angular/core';
Input() t;
You should try providing base name while providing input for the component:
#Input('t') t;
Hope this helps.

Resources