Angular 2 component without a view - javascript

Is it possible to use Angular 2 without using a template or an #View?
I'm looking for a similar way like you did the following in example:
Angular 1
index.html
<div ng-controller="appcontroller">
<div ng-class="{active: isActive()}">
.....
</div>
</div>
app.js
angular.module('app', []).controller('appcontroller', function(){
$scope.isActive = function(){
return true;
}
});
I was guessing it would look something like this, if it was possible:
Angular 2
index.html
<app>
<div [ngclass]="{active: isActive()}">
.....
</div>
</app>
app.ts
import {Component} from 'angular2/core';
#Component({
selector: 'app'
})
export class AppComponent {
isActive(){
return true;
}
}
But unfortunately I'm getting the error:
... must have either 'template', 'templateUrl', or '#View' set.
I don't really like putting html in Javascript, so I hope there some sort of workaround or way to do this.

In fact, you should implement the AppComponent like this:
import {Component} from 'angular2/core';
#Component({
selector: 'app'
template: `
<div [ngClass]="{active: isActive()}">
.....
</div>
`
})
export class AppComponent {
isActive(){
return true;
}
}
or using the templateUrl property:
import {Component} from 'angular2/core';
#Component({
selector: 'app'
templateUrl: 'component.html'
})
export class AppComponent {
isActive(){
return true;
}
}
and use the component like this:
<app></app>
If you put some HTML inside the app tag, this means that you want to provide some content to the component that can be included in the component template using ng-content. Here is a sample: Angular 2 Template Component.
Hope it helps you,
Thierry

Related

Angular2 ngFor not working

I am trying to implement a basic shopping list, but my ngFor in Angular is not working.
import { Component, View } from 'angular2/angular2';
#Component({
selector: 'my-app'
})
#View({
template: '<h1>{{title}}</h1><ul><li *ngFor="let i of items"><span>{{i}}</span></li></ul>'
})
export default class MyAppComponent {
title = 'ShoppinList';
items = ['Milk','Ham','Eggs'];
}
The only thing that appears is "loading..." and I am getting more than 10 cryptic errors.
Without trying it first I noticed an error in the import statement at the top. Should be:
import { Component } from '#angular/core'
#View() was removed almost a year ago. If you see examples that use it, just move the content to the #Component() decorator while directives and pipes were moved from #Component() to #NgModule()s declaration.
You need to add CommonModule to #NgModule({ imports: [CommonModule], ...}) export class SomeModule{} in every module where you want to use ngFor (or other directives shippled with Angular - BrowserModule already includes CommonModule).
its good way to use ngIf and use your template inside your component properties.
import { Component, View } from 'angular2/angular2';
#Component({
selector: 'my-app',
template : '<div>
<h1>{{title}}</h1>
<ul *ngIf="items">
<li *ngFor="let i of items"><span>{{i}}</span></li>
</ul>
</div>'
})
export default class MyAppComponent {
title : string = 'ShoppinList';
items : Array<string> = ['Milk','Ham','Eggs'];
}
You don't have to use #View here.
#Component({
selector: 'my-app',
template: `
<div>
{{title}}
<ul><li *ngFor="let i of items"><span>{{i}}</span></li></ul>
</div>
`,
})
export class App {
title = 'ShoppinList';
items = ['Milk','Ham','Eggs'];
}
Working plunker

Semantic UI with Angular2 - How to set Sidebar settings from jQuery in a component?

I have an Angular2 application and I want to use Semantic UI. However, there are some jQuery configurations like below that I have to run after a component loaded:
$('#app .ui.sidebar')
.sidebar({context:$('#app')})
.sidebar('setting', 'transition', 'overlay')
It is not working by importing the js file in the head of index.html or writing it in a <script> tag inside of a component template. Is there a "typescript way" to do that or how can I use a js file inside of a component?
I found this link about using jQuery in directives, then I created a sidebar directive:
import {Directive, ElementRef, OnDestroy, OnInit, Input} from '#angular/core';
import {HostListener} from "#angular/core/src/metadata/directives";
declare var $: any
#Directive({
selector: '.ui.sidebar'
})
export class SidebarDirective implements OnInit, OnDestroy {
#Input() context: string;
constructor(private el: ElementRef) {
}
public ngOnInit() {
$(this.el.nativeElement)
.sidebar({context: this.context})
.sidebar('setting', 'transition', 'overlay');
}
public ngOnDestroy() {
}
}
Then, I used it in the template:
<div id="app">
<div context="#app" class="ui left vertical menu sidebar"></div>
<div class="pusher"></div>
</div>
I have spent quite some time to get this working although it is rather simple in the end. Hope to save you some time ...
There is no need to create a directive, you can use the jQuery command as you would use with JavaScript (described at https://semantic-ui.com/modules/sidebar.html#/usage). However, "$" has to be declared and the command has to be located in a TypeScript function ("toggle()"):
import {Component} from '#angular/core';
declare var $: any;
#Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
toggle() {
$('.ui.sidebar').sidebar('toggle');
}
}
The corresponding section of the template may look like this:
<div class="ui fixed inverted main menu">
<a (click)="toggle()" class="launch icon item">
<i class="content icon"></i>
<p style="padding-left:1em">Menu</p>
</a>
</div>
Don't forget to add jQuery to the scripts section of .angular-cli.json:
"scripts": [
"../node_modules/jquery/dist/jquery.js",
"../node_modules/semantic-ui-css/semantic.min.js"
],
I'm using Semantic UI 2.2.12 which already depends on jQuery 3.2.1. Angular version is 4.4.4 running on node.js 6.11.2.
import { Component, OnInit } from '#angular/core';
declare var $:any;
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app works!';
ngOnInit(){
$('#app .ui.sidebar')
.sidebar({context:$('#app')})
.sidebar('setting', 'transition', 'overlay') ;
}
}

Angular 2 update child component's class list from parent

I'm new to Angular 2 and I need some help with the following issue.
I have a parent and a nested, child component:
// The Parent:
import { Component, ViewChild } from 'angular2/core';
import {Preloader} from 'components/preloader/preloader';
#Component({
selector: 'console',
providers: [Preloader],
directives: [Preloader],
templateUrl: 'components/console/console.html'
})
export class Console {
#ViewChild(Preloader) preloader: Preloader;
constructor(preloader: Preloader) {
this.preloader = preloader;
}
ngAfterViewInit() {
this.preloader.showConsole();
}
}
// ...and the Child
import {Component} from 'angular2/core';
#Component({
selector: 'preloader',
template: `
<div [ngClass]="style"></div>
`
})
export class Preloader {
constructor() {
this.style = {
fullscreen: true,
done: false
};
}
showConsole() {
// this is not working:
this.style.done = true;
}
}
I'd like to set both variables in style object to true when the parent component is fully mounted. That actually happends, but in the Preloader's template I see only fullscreen class even after showConsole method was called and style.done was set to true.
console.html template is just like this:
<div class="main-window">
<preloader></preloader>
</div>
I just tested and your solution is working without any problem.
But if you still say fullscreen class remains same then you can consider below solution,
ngAfterViewInit() {
setTimeout(()=>{
this.preloader.showConsole();
},0)
}
showConsole() {
this.style.fullscreen = false; //<<<===added.
this.style.done = true;
}
I've figured it out!
The problem was in the communication between two components. First of all this is how I should have pass the data in the template:
<div class="main-window">
<preloader [start]='showConsole'></preloader>
</div>
But, the most important thing, it also requires to specificate input variables in the child #Component like this:
#Component({
inputs: ['start'],
selector: 'preloader',
template: `<div [ngClass]="style"></div>`
})

Angular 1 directive inside angular 2 application

We created an Angular 2 application using this awesome Angular2 Seed which works very well. So the question that I have is, how can I upgrade this Angular 1 directive:
import template from './sbgOutlineButton.html!text';
var app = angular.module('sbgOutlineButton', []);
app.directive('sbgOutlineButton', function() {
let link = function(scope, element, attributes) {
if (attributes.icon === undefined) {
let materialIcon = element.find('i.material-icons');
materialIcon.addClass('hidden');
}
};
return {
link: link,
restrict: 'E',
template: template,
replace: true,
transclude: true,
scope: { icon: '#' }
};
});
export default app;
So that I can use it in the following Angular 2 component:
import { Component, OnInit, ChangeDetectionStrategy } from '#angular/core';
import { UpgradeAdapter } from '#angular/upgrade';
#Component({
moduleId: module.id,
selector: 'test-page',
templateUrl: 'testpage.page.html',
styleUrls: ['testpage.page.css']
})
export class TestPage implements OnInit {
constructor() { }
ngOnInit() { }
}
Do you guys maybe have any idea on how I will be able to accomplish this? Is it even possible? Because a lot of the other articles that I have found during my research suggests that your "base" application should be Angular 1...
Thanks in advance.
Francois
How about converting your angular1 directive to angular2 directive?
NOTE: I don't know whether it will be useful or not but just have a look.
Look at the demo here : https://plnkr.co/edit/4Fhtm76iJl0aQmgjO7n0?p=preview
customeDirective.ts
import {Directive, Attribute,ElementRef,Renderer} from '#angular/core';
#Directive({
selector: '[myAttr]'
})
export class myDir {
constructor(#Attribute('icon') private icon,private el:ElementRef,private rd: Renderer){
console.log(this.icon);
if(this.icon===null){ //<--- you can play here as per your need.
console.log('icon is undefined');
}
else{
rd.setElementClass(el.nativeElement, 'myClass',true);
}
console.log(el.nativeElement);
}
}
AppComponent.ts
//our root app component
import {Component} from '#angular/core';
import {myDir} from 'src/customDirective';
#Component({
selector: 'my-app',
directives:[myDir],
template:
`
<style>
.myClass{
color:red;
background:yellow;
}
</style>
<div myAttr icon="myIcon">Angular2</div> <!-- icon attribute is present so it will add the class -->
<!-- OR USE BELOW HTML INSTEAD OF ABOVE -->
<div myAttr>Angular2</div> <!-- icon attribute is not present so it gives null -->
`
})
export class App {}
You need to upgrade to angular2 by using "#angular/upgrade": "2.0.0-rc.4",
Guide
Because a lot of the other articles that I have found during my
research suggests that your "base" application should be Angular 1...
It's if you have a already angular 1 project and you want to upgrade to one. Angular2 don't need angular1 as base
writing directive in angular2
import { Directive, ElementRef, Input } from '#angular/core';
#Directive({ selector: '[myHighlight]' })
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
My First Attribute Directive
Highlight me!
import { Component } from '#angular/core';
import { HighlightDirective } from './highlight.directive';
#Component({
selector: 'my-app',
templateUrl: 'app/app.component.html',
directives: [HighlightDirective]
})
export class AppComponent { }
you Don't need to mix up angular1 into two..

Angular 2 (Ionic 2): can't "render" Component inside Page

I built an Angular 2 Component:
import {Component, View} from 'angular2/core';
#Component({
selector: 'sidemenu'
})
#View({
templateUrl: 'build/pages/menu/menu.html',
})
export class Menu {
}
in a Page component, I can't use it in the template:
import {Menu} from '../menu/menu';
#Page({
templateUrl: 'build/pages/content/content.html'
})
export class PO {
}
content.html:
<ion-content>
<sidemenu></sidemenu>
</ion-content>
isn't replaced by the Menu component's "html" (build/pages/menu/menu.html). But if I use dynamicComponentLoader to load the component inside an element from the DOM, it works (I did this to check if the component is ok).
Am I missing something?
directives: [Menu]
import {Menu} from '../menu/menu';
#Page({
templateUrl: 'build/pages/content/content.html',
directives: [Menu]
})
export class PO {
}
I don't know Ionic but usually in Angular2 you need to list components you use in the template in the #Component({ ..., directives: [Menu], ...}){ ...}

Categories

Resources