I have generated component using cli
"ng generate component registration"
it created following files
registration.component.html
registration.component.scss
registration.component.spec.ts
registration.component.ts
Now, I haved added a css class in scss file
.loginBox {
width: 260px;
}
Now in the html file
<p class="loginBox"> test </p>
It pointed out that loginBox is undefined CSS in my IDE and when I tested in ng serve it didnt show the css was applied.
When I do autocomplete on the class= I saw there are alots of css that I didnt add such as L0, L1, L2, L3 ....so where does those css coming from and why doesnt my local css work? Edit: those css seems like bootstrap css or somewhat buildin css there are something like mat-action-row or other type of css I dont think I included them.
The ts file I have included styleUrls: ['./registration.component.scss']
Edit: even if I added it the global styles.scss it is still says the loginBox is undefined CSS. It is likely some config or something is missing....I cant figure out what it is...
Edit:
registration.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-registration',
templateUrl: './registration.component.html',
styleUrls: ['./registration.component.scss']
})
export class RegistrationComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
registration.component.scss
.loginBox {
/* color: #4C4633; */
/* font-size: 12px; */
/* margin-bottom: 10px; */
/* padding: 10px 0px 10px 10px; */
width: 260px;
}
registration.component.html
<p class="loginBox">
registration works!
</p>
<div class="loginBox"> test </div>
Above registration folder..
app.component.html
<div class="container-fluid p-0">
<router-outlet></router-outlet>
</div>
app.module.ts
const routes: Routes = [
{ path: '', component: RegistrationComponent}
];
#NgModule({
declarations: [RegistrationComponent],
imports: [
BrowserModule,
RouterModule.forRoot(routes)
],
providers: [PreviousUrlService, {provide: APP_BASE_HREF, useValue : '/' }],
bootstrap: [AppComponent]
})
export class AppModule { }
See this answer here. Use encapsulation: ViewEncapsulation.None in the #component definition.
is scss correctly read? try to run this command
ng config schematics.#schematics/angular:component.styleext scss
then, re-run you project
try:
:host ::ng-deep{
.loginBox {
width: 260px;
}
}
Related
I have the following component:
// Typescript
#Component({
selector: 'form-button',
templateUrl: './form-button.component.html',
styleUrls: ['./form-button.component.scss']
})
export class FormButtonComponent {}
//form-button.component.html
<div class="form-button-wrapper">
<div class="content"></div>
</div>
//form-button.component.scss
.form-button-wrapper {
width: 100%;
height: 100%
}
In the html, will looks like this:
<head>...</head>
<body>
....
<form-button>
<div class="form-button-wrapper">
<div class="content"></div>
</div>
</form-button>
....
</body>
I want t defined a width and weight to the <form-button> instead of in the <div class="form-button-wrapper">.
How can I do that?
Yes, just use the :host selector. It gives you access to the wrapping angular element.
//form-button.component.scss
:host {
// insert your styles here
}
.form-button-wrapper {
width: 100%;
height: 100%
}
I am trying to create a dynamic button with an onclick event. The showname() defined the on same Component.ts. But there is no response on clicking the button
Component.ts
createtooltip() {
this.tooltip = document.createElement('div');
this.tooltip.style.cssText =
'position:absolute; background:black; color:white; padding:4px;z-index:10000;' +
'border-radius:2px; font-size:12px;box-shadow:3px 3px 3px rgba(0,0,0,.4);' +
'opacity:0;transition:opacity 0.3s';
this.tooltip.innerHTML = '<button id="popup" (click)="showname()" >Copy!</button>';
document.body.appendChild(this.tooltip);
}
showname() {
console.log("Hi User");
}
Could anyone help me to find the solution?
You won't have access to the document object everywhere.
So, you shouldn't be using document functions to do DOM manipulations. All these DOM Manipulations should be done only using Rendere2. If there's anything that you want to access on the DOM, you should do it using #ViewChild
Here's an Example:
import { Component, Renderer2, ElementRef, ViewChild } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular';
#ViewChild('tooltip') tooltip: ElementRef;
constructor(private renderer: Renderer2) {}
createtooltip() {
this.renderer.setAttribute(this.tooltip.nativeElement, 'class', 'my-button');
const button = this.renderer.createElement('button');
this.renderer.setProperty(button, 'id', 'popup');
this.renderer.setProperty(button, 'innerText', 'Copy');
this.renderer.listen(button, 'click', (event) => {
this.showname();
})
this.renderer.appendChild(this.tooltip.nativeElement, button);
}
showname() {
console.log("Hi User");
}
}
In template:
<button (click)="createtooltip()">Create Tooltip</button>
<div #tooltip>
</div>
In CSS:
p {
font-family: Lato;
}
.my-button {
position:absolute;
background:black;
color:white;
padding:4px;
z-index:10000;
border-radius:2px;
font-size:12px;
box-shadow:3px 3px 3px rgba(0,0,0,.4);
opacity:0;
transition:opacity 1s linear;
}
Here's a Sample StackBlitz for your reference.
I solved this problem by the other way
<a ngFor="let link of links" (click)="actions[link]()">Click</a>
`
actions: any = {
link1: () => this.func1(),
link2: () => this.func2()
}
`
angular doesnt compile the dynamic created HTML elements . u have to use ng-template like this :
<ng-template #myTemplate>
<div styles="...">
<button id="popup" (click)="showname()" >Copy!</button>
</div>
</ng-template>
It would be better to create the button with directs like *ngFor or *ngIf rather than create the elements like you do with Jquery.
This is due to the nature of Angular, which prioritizes and eases the usage of directives over simple javascript.
to do this you can :
HTML :
<button id="popup" (click)="showname()" *ngIf='elements.showNameButton==true' >Copy!</button>
** TS :**
elements={
showNameButton:false
}
createtooltip(){
this.elements.showNameButton =true;
}
showname() {
console.log("Hi User");
}
I love the animejs libary form: https://github.com/juliangarnier/anime It fast, clear and easy to implement, except in Ionic of a Angular project.
I've take a look to the post: anime.js not working in Ionic 3 project but, it doenst work for me.
The image (who I what to animate) doens't animate.
Does anybody has this working? And please share a solution?
What I've done so far:
Install animejs with npm: the package.json is updated with: "animejs": "^2.2.0"
Animejs is availible in the node_modules
With a custom copy-lib the anime.min.js is loaded in the index.html, see:
const existingConfig = require('../node_modules/#ionic/app-scripts/config/copy.config');
module.exports = Object.assign(existingConfig, {
copyFontawesomeFonts: {
src: ['{{ROOT}}/node_modules/font-awesome/fonts/**/*'],
dest: '{{WWW}}/assets/fonts'
},
copyFontawesomeCss: {
src: ['{{ROOT}}/node_modules/font-awesome/css/font-awesome.min.css'],
dest: '{{WWW}}/assets/css'
},
copyAnimeJS: {
src: ['{{ROOT}}/node_modules/animejs/anime.min.js*'],
dest: '{{WWW}}/assets/js'
},
}
);
The index.html looks like:
...
<!-- Font-awesome -->
<link href="assets/css/font-awesome.min.css" rel="stylesheet"/>
<!-- Anime JS -->
<link href="assets/js/anime.min.js" rel="stylesheet"/>
...
The anime.min.js is available in the index.html
I import the amine in my login.ts file like:
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import * as anime from 'animejs';
...
Load it in the constructor:
anime({
targets: '#authImg',
translateY: -50,
elasticity: 800,
duration: 2500,
direction: 'alternate',
easing: 'easeInOutCubic',
loop: true
});
Which have to animate the following html:
<img src="assets/img/auth.png" alt="" id="authImg" />
But nothing happened...
I think you don't have to link assets/js/anime.min.js to your index.html neither copy js with ionic app script.
Just import anime.js as follows:
import * as anime from 'animejs';
Then make sure you are setting your animation once the view is loaded (in ionViewDidLoad for example.
I've just run this example and it works fine:
Example.ts:
import { Component } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import * as anime from 'animejs';
#Component({
selector: 'page-example',
templateUrl: 'example.html',
})
export class ExamplePage {
constructor(public navCtrl: NavController, public navParams: NavParams) {
}
ionViewDidLoad() {
anime({
targets: '#cssSelector .el',
translateX: 250
});
}
}
Example.html:
<ion-header>
<ion-navbar>
<ion-title>Example</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<div id="cssSelector">
<div class="line">
<div class="square el"></div>
</div>
</div>
</ion-content>
example.scss:
page-example {
.square, .circle {
pointer-events: none;
position: relative;
width: 28px;
height: 28px;
margin: 1px;
background-color: currentColor;
font-size: 12px;
}
}
If you are from 2020 import it like this
import anime from 'animejs/lib/anime.es';
Problem: I want a single component (spacer) that will have width 100% and a height that can be input wherever it appears in the HTML (home.html in this test):
number 1
<spacer height="'200px'"></spacer>
no more
The spacer.html:
<div class="container-fluid spaceContainer" [ngStyle]="{'height': 'height'}">
spacer is here <<<--- this text is just for testing
</div>
The scss:
.spaceContainer {
width: 100%;
border: 1px solid red;
display: flex;
flex-direction: row;
}
Spacer.ts:
import {Component, Input, OnInit} from '#angular/core';
#Component({
selector: 'spacer',
templateUrl: './spacer.component.html',
styleUrls: ['./spacer.component.scss']
})
export class SpacerComponent implements OnInit {
#Input() height: string;
constructor() {
}
ngOnInit() {
console.log('height is '+ this.height);
}
}
When it runs, the console.log gives: height is '200px'
but the height of the red-bordered box is just enough to hold the 'spacer is here' text.
I struggle understanding binding a bit so I've tried:
<spacer height="200px"></spacer>
Console: height is 200px, which I thought would work but no change. Not understanding attr, I tried variants of attr.height.
This has to be easy and may help clear up my misunderstanding of how binding works.
Thanks in advance,
Yogi
Your mistake is located at this line:
[ngStyle]="{'height': 'height'}"
^^^^^^^^^^
it should be just height
You're binding height to string 'height' but you should bind it to height property of your component something like:
[ngStyle]="{'height': height}">?
or
[style.height]="height"
I have two components: BuilderComponent and InputTextComponent.
With drag and drop I put a directive in the sortableList element of the BuilderComponent template. With the inspector I can see the directive appears in the sortablelist DOM element:
<div class="row">
<div class="col-md-12">
<ul id="sortableList">
<zbjfb-input-text></zbjfb-input-text>
</ul>
</div>
How can I force the BuilderComponent to detect that the content of the template is changed since the last compile and then re-render the template with the new added directive so I can see the new compiled InputTextComponent.
BuilderComponent:
import { Component } from '#angular/core';
#Component({
selector: 'zbjfb-builder',
template: '
<div class="row">
<div class="col-md-12">
<ul id="sortableList">
</ul>
</div>
</div>
'
})
export class BuilderComponent {}
InputTextComponent:
import { Component } from '#angular/core';
#Component({
selector: 'zbjfb-input-text',
templateUrl: './input-text.component.html',
styleUrls: ['./input-text.component.css']
})
export class InputTextComponent {}
Any idea?
Thanks in advance.
If your drag'n'drop solution is HTML5 based, maybe you can make use of HostListener decorator from '#angular/core' to hack your drag and drop exchange logic:
Add something like this on your drop area component:
#HostListener('drop', ['$event'])
onDrop(event: any) {
//do something
}
And something like this on your draggable component:
#HostListener('dragstart', ['$event'])
onDrag(event: any) {
//do something
}
HostListeners provide you ways to implement conventional listeners for element events like onmousedown, onkeyup, ondrop, ondrag.
Then think of some logic to identifiy what's being dragged/dropped and change the drag area component model. Here's some functional code I've made inspired by W3Schools topic on drag'n'drop:
import { Component, HostListener, Input } from '#angular/core';
// The draggable component
#Component({
selector: 'dragme',
template: `
<div draggable="true">
Drag {{name}}!
</div>
`,
styles: [`
[draggable] {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
-khtml-user-drag: element;
-webkit-user-drag: element;
background-color: #AAA;
border: 1px solid black;
padding: 24px;
margin: 12px;
}
`]
})
export class DragMe {
#Input()
name:string = "";
#HostListener('dragstart', ['$event'])
onDrag(event:any){
event.dataTransfer.setData("name",this.name);
}
}
// The drop area component
#Component({
selector: 'drop',
template: `
<div class="drop">
Drop over me!
<ul>
<li *ngFor="let i of items">{{i}}</li>
</ul>
</div>
`,
styles: [`
.drop{
border: 1px solid black;
padding: 24px;
}
`]
})
export class DropOverMe {
items:string[] = [];
#HostListener('dragover', ['$event'])
onDragover(event:any){
event.preventDefault();
}
#HostListener('drop', ['$event'])
onDrop(event:any){
event.preventDefault();
var name = event.dataTransfer.getData("name");
this.items.push(name);
}
}
// The functional example
#Component({
selector: "drag-example",
template: `
<dragme name="Bob"></dragme>
<dragme name="Alice"></dragme>
<dragme name="Carl"></dragme>
<drop></drop>
`
})
export class DragExample{
}
Full code at: https://github.com/rafaelodon/angular2-html5-dragndrop-example