How To Add CSS to router-outlet element - html

I have some code that looks like this:
<section>
<div style="height: 100%; max-width: 10%; background-color: deepskyblue;">my content</div>
<router-outlet style="height: 100%; min-width: 90%; background-color: gold;"></router-outlet>
</section>
I want the div to work as a side-bar with the router-outlet taking up the remaining 90% of the space. But what ends up happening is that the content displayed from the router-outlet is pushed beneath the div rather than beside it. It also appears that no CSS is being applied to the router-outlet, as the background color doesn't change. Is there any way to get CSS to make changes to this router-outlet?

simple solution is to to just put router-outlet in a style div.
<section>
<div style="height: 100%; max-width: 10%; background-color: deepskyblue;">my content</div>
<div style="height: 100%; min-width: 90%; background-color: gold;">
<router-outlet ></router-outlet>
</div>
</section>

Short answer
Use:
:host { background: cornflowerblue; }
as the css for the hosted component, to change background of the router outlet.
Long Answer:
Angular CSS pseudo selector/modifier
You can affect the hosting component with the :host modifier. In the case that you would like to change the router oulet styling, add css to the component that will be hosted.
e.g. Change the router outlet blue when showing the page-edit component.
// This is your routing to place your page component in the outlet when
navigating to the edit/1 url.
const routes: Routes = [
{
path: 'edit/:pageId',
component: PageComponent,
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class PageEditorRoutingModule {}
// PageComponent - stub of component to be rendered in outlet.
#Component({
selector: 'app-page-editor',
templateUrl: './page-editor.component.html', //implement as desired.
styleUrls: ['./page-editor.component.scss']
})
export class PageEditComponent {
// Your implementation
}
// Put this in your page-editor.component.scss to change the router outlet background blue
:host{
background: cornflowerblue;
}

Related

How to change style of a child angular component to be same size as another child component

I have been struggling with this for a quite some time now, and i couldn't find a sufficient answer. Basically i have one parent component which html goes as follows:
<div class="container">
<child-one></child-one>
<child-two></child-two>
</div>
the problem is that the child-one component has its size set as auto, with some padding to look good,
child-one {
width: auto;
height: auto;
padding: 0.5rem;
}
and child-two has a fixed width and height in it's own scss.
child-two {
width: 10rem;
height: auto;
}
is there a way to somehow change the width of child-two in the parent without editing the child-two?
I was hoping for something along the lines of storing the width of the child-one, and setting the width of child-two to the same value.
child-one {
width:auto;
padding: 0.5rem;
$width: this.width !global //idk about this one
}
child-two {
width: $width
padding: 0.5rem
}
please note that the child-one and child-two scss don't look this way in the code, and are normally written, this is just for the purpose of simplifying the question
Is this what you are looking for?
app.component.html - Parent Component
<child-one #childOne></child-one>
<child-two #childTwo></child-two>
<br>
<button (click)="changeWidth()">Change child two width</button>
app.component.ts
export class AppComponent {
#ViewChild('childOne', {
read: ElementRef
}) childOne: ElementRef;
#ViewChild('childTwo', {
read: ElementRef
}) childTwo: ElementRef;
constructor(private renderer: Renderer2) {}
changeWidth() {
const childOneWidth = this.childOne.nativeElement.getElementsByClassName('child-one')[0].offsetWidth;
const childTwoElement = this.childTwo.nativeElement.getElementsByClassName('child-two')[0];
this.renderer.setStyle(childTwoElement, 'width', `${childOneWidth - 2}px`);
}
}
Here is the working Stackblitz
Suggestion
#SivakumarTadisetti's suggestion is a valid suggestion, alternatively, you could use ngStyle to provide dynamic styling for the component or ngClass for conditionally applying style class to the component. You could, which requires more code, also write a directive that changes the style behaviour of the component based on certain conditions.
Example using ngStyle
https://stackblitz.com/edit/stack-help-01

AngularDart App Layout issue with material-navigation

I've been trying to implement a material design site using AngularDart, and I've hit a wall using the angular_components App Layout setup. For the life of me I can't figure out how to change the look of the nav class="material-navigation" content to match the examples (things like background, text color, and text highlight color). Currently the text has a grey box surrounding it rather than matching the header color. It doesn't seem like these properties are set in layout.scss, so I'm stumped. I've made minimal changes to the layout.scss file, which I've posted below. Any insight into what I'm missing? Thanks in advance :)
AngularDart Material Nav
import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';
import 'package:angular_components/material_icon/material_icon.dart';
import 'package:angular_components/material_button/material_button.dart';
import 'package:angular_components/material_list/material_list.dart';
import 'package:angular_components/material_list/material_list_item.dart';
import 'package:angular_components/material_toggle/material_toggle.dart';
import 'package:angular_components/app_layout/material_persistent_drawer.dart';
import 'dart:async';
#Component(
selector: 'my-app',
directives: [
coreDirectives,
MaterialIconComponent,
MaterialButtonComponent,
MaterialToggleComponent,
MaterialListComponent,
MaterialListItemComponent,
MaterialPersistentDrawerDirective],
templateUrl: 'app_component.html',
styleUrls: [
//Holds modifications for angular_components style sheets. Particularly
//app_layout, which is *not* a component but a weird grouping of components
//and styles.
'main.css',
'app_component.css',
],
providers: [ClassProvider(NomiService)],
)
...
#import 'package:angular_components/app_layout/layout';
.material-header {
background-color: $mat-vanilla-red-400; //vs. $mat-indigo-500
}
// A row within the header.
.material-header-row {
/// Class uses for the title inside of a header.
.material-header-title {
left: auto; //vs. $mat-grid * 10;
height: 36px; //$mat-header-height; //vs. $mat-title-font-size
font-size: 36px;
//border: 3px solid green; Use to check work!
//Used to center text!
margin-left: 37.5%;
margin-right: 37.5%;
text-align: center;
width: 25%;
}
.material-navigation{
border: 3px solid green;
}
}
<header class="material-header shadow">
<div class="material-header-row">
<material-button icon class="material-drawer-button" (trigger)="drawer.toggle()">
<material-icon icon="menu"></material-icon>
</material-button>
<img src="favicon.png" width="30">
<span class="material-header-title">Nomi</span>
<div class="material-spacer"></div>
<nav class="material-navigation">
<a>Test</a>
</nav>
</div>
</header>
<material-drawer persistent #drawer="drawer">
<material-list>
<div group>
<material-list-item>
<material-icon icon ="inbox"></material-icon>Inbox
</material-list-item>
<material-list-item>
<material-icon icon ="star"></material-icon>Star
</material-list-item>
<material-list-item>
<material-icon icon ="send"></material-icon>Sent Mail
</material-list-item>
<material-list-item>
<material-icon icon ="drafts"></material-icon>Drafts
</material-list-item>
</div>
</material-list>
</material-drawer>

Css changed after inputting router-outlet

I was developing a login screen within angular with the within the app.component.html as such:
app.component.ts
<div class="container">
<app-login></app-login>
</div>
and css as such:
login.css
.form-group {
display: block;
margin-bottom: 15px;
}
.form-group label {
display: block;
margin: 0 0 5px 0;
}
app.component.css
.container {
display: grid;
height: 100%;
}
app-login {
width: 100%;
max-width: 274px;
place-self: center;
}
However, since I have now incorporated routing into my app, I display the login page using the <router-outlet> component, but this has ruined the CSS of the login page is it once was...
app.component.ts
<div class="container">
<router-outlet></router-outlet>
</div>
How can I change my CSS files such that I can get back the look I once had?
Here is a stackblitz to my example
Update
Solution found to the missing CSS (see below)
However now it appears is hogging much of the screen, pushing my element downward?
You need to set
encapsulation: ViewEncapsulation.None
on the AppComponent to allow styles to affect also those components which are used inside AppComponent.
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
name = 'Angular';
}
But it will be better to use styles on those components for which they were declared.
This is a working Stackblitz.
You were targeting <app-login> in the app.component.css file and styling it to have a fixed width and align it center. What you have to remember is that, Angular enforces emulated view encapsulation and also when you are using router, <app-login> may be changed to some random dynamic name at run time thereby making your css classes that you might have written in app.component.css ineffective.
Its always a best practice to write styles for a component in its respective CSS file rather than the root components css file.
Here is a changed Stackblitz
Here is the result:

How can I apply different (full page) backgrounds for different Angular 5 pages?

Currently I am using Angular 5 to make an SPA.
I want to fill the entire screen with a background (not just one component) but I want different backgrounds for each page, how can I achieve this?
I have tried this code in the component.css of the concerning page (for example
home.component.css):
body {
background-color: aqua;
}
(using background-color as an example)
Using this method, I thought I could override the main body background per component but it does not seem to work, the page remains empty.
I would appreciate any help you can give me, thanks in advance.
I think your issue is that when you add
body {
background-color: aqua;
}
to your component css, Angular rewrites it to something like
body[_ngcontent-c0] {
background-color: yellow;
}
You can see it in dev tools if you check. Because of this, the style does not get attached to the body. You can use Renderer2 to change the body style for each component. For example:
import { Component, Renderer2 } from '#angular/core';
#Component({
selector: 'home',
templateUrl: './home.component.html',
styleUrls: [ './home.component.css' ]
})
export class HomeComponent {
name = 'Home';
constructor(private renderer: Renderer2) {
this.renderer.setStyle(document.body, 'background-color', 'yellow');
}
}
Similar Question: Angular2 add class to body tag
Angular documentation: https://angular.io/api/core/Renderer2
Hope this helps.
Add the following component in all the components that need background color. The color to be used can be passed in the input attribute:
import { Component, OnInit } from '#angular/core';
import { Input } from '#angular/core';
#Component({
selector: 'app-bg',
templateUrl: './bg.component.html',
styleUrls: ['./bg.component.scss']
})
export class BgComponent implements OnInit {
#Input() bgColor = 'red';
constructor() { }
ngOnInit() {
}
public getBgColor() {
return {
'background-color': this.bgColor
};
}
}
Here is the CSS bg.component.scss:
.bg {
position: fixed;
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-position: center;
background-attachment: fixed;
background-size: cover;
overflow: auto;
}
And the template bg.component.html:
<div class="bg" [ngStyle]="getBgColor()"></div>
Finally in all the components that need background color, add this:
<app-bg [bgColor]="'blue'"></app-bg>

Is it possible to have sticky div inside an angular form?

I'm working with angular and angular-material.
Inside a page, I have a form, and some buttons (grouped in a div) which are depending on this form.
But, I'd like to have these buttons (the div) sticking the bottom of the page, even if I scroll.
Here's some code :
<form (ngSubmit)="update()" #updateForm="ngForm">
<div> some content with inputs and selects </div>
<div class="button-container"> buttons like save, cancel, ... </div>
</form>
and :
.button-container {
position: sticky !important;
bottom: 0;
float: right;
z-index: 999;
}
If I put the buttons out of the form, they don't work anymore. Thing is, it'd be better if I don't change the buttons' methods, and only modify HTML and CSS.
What I did doesn't work, any idea ?
I did this on plunker, with the same CSS properties as my project https://plnkr.co/edit/pw7zOruWwhV0o1Vya717?p=preview
In case you cannot reproduce the failing version in plunkr, then some other css-styling in your project might be preventing the sticky-position.
In my case the sticky-position did not work in case the containing div had
overflow:hidden;
Maybe you have the value set on the containing div?
I think I had the same problem. Normally I would use position fixed but this wouldn't work because material used transform: translate3d(0,0,0). This made fixed to behave like absolute. To solve this problem I used the below:
//Place this in your form
<app-fnls-displacer>
<div style="position: fixed; right: 30px; bottom: 30px; padding-bottom: 2em; z-index: auto">
<button mat-fab class="fab" type="submit" (click)="myfunction()">
<mat-icon>add</mat-icon>
</button>
</div>
</app-fnls-displacer>
This is the component and directive used:
import {AfterViewInit, Component, Directive, OnDestroy, TemplateRef, ViewChild, ViewContainerRef} from '#angular/core';
import {Overlay, OverlayRef, OverlayConfig, TemplatePortal} from '#angular/material';
#Directive({ selector: '[displacerPortal]' })
export class DisplacerPortalDirective extends TemplatePortal<any> {
constructor(templateRef: TemplateRef<any>, viewContainerRef: ViewContainerRef) {
super(templateRef, viewContainerRef);
}
}
#Component({
selector: 'app-fnls-displacer',
template: `
<ng-template displacerPortal>
<ng-content></ng-content>
</ng-template>
`
})
export class DisplacerComponent implements OnDestroy, AfterViewInit {
private _config = new OverlayConfig();
#ViewChild(DisplacerPortalDirective)
private _portal: DisplacerPortalDirective;
private _overlayRef: OverlayRef = undefined;
constructor(private _overlay: Overlay) {}
public ngOnDestroy() {
this._overlayRef.detach();
}
public ngAfterViewInit() {
this._overlayRef = this._overlay.create(this._config);
this._overlayRef.attach(this._portal);
}
}
I found it on a material GitHub page. It places the content inside it directly to the body, so that you can use position: fixed.
Set a fixed height to the scrolling element and fix the button position:
<div style="height:calc(100vh - 100px) !important; overflow: scroll !important" class="mat-tab-body-content ng-trigger ng-trigger-translateTab">
......
<button style="top: calc(100vh - 50px) !important; position: fixed !important" md-button (click)='alert("clicked!");'>button</button>
Plunker