ng-bootstrap - Typeahead dropdown width - css

I started using the ng-bootstrap Typeahead component and I'm pretty happy with that.
One thing I would like to achieve is to get the dropdown items to have the same width as the input field, while the default behavior applies a width accordingly to the text length. It should be basic CSS...
I created a basic Example in Plunker.
As you can note, the applied style is ignored:
.dropdown-menu { width: 100%;}
While if I use browser dev tools, and apply the same it is applied.
Any idea on how to achieve the result, by using CSS?

Add encapsulation: ViewEncapsulation.None to the component
import {Component, ViewEncapsulation} from '#angular/core';
#Component({
selector: 'ngbd-typeahead-template',
templateUrl: 'src/typeahead-template.html',
styleUrls: ['src/typeahead-template.css'],
encapsulation: ViewEncapsulation.None
})
See updated plunker
Without ViewEncapsulation.None, the styles applied in this component will only effect this component and not any other component on this page.
Read this for more information

For me works ng-deep. Looks more safe and scoped:
::ng-deep .dropdown-menu { width: 100%; }

This is how I made it work within responsive col :
::ng-deep ngb-typeahead-window.dropdown-menu {
width: calc(100% - 30px);
}
or
::ng-deep .dropdown-menu.show {
width:calc(100% - 30px);
}
Not sure which one is the best option but I tend to think of the first one.

#Nandita's answer is correct, directly apply a width to dropdown menu won't affect.
And you want the dropdown menu to have same width as input, so you should add below CSS to her answer:
.dropdown-menu { width: 300px;}
Check result:
https://next.plnkr.co/edit/YvOymCLAwYgU3VmJ

This code 100% work, but with the class .dropdown-menu any other dropdown will be changed
::ng-deep .dropdown-menu { width: 100%; }
So I just used this code with ngb-typeahead- as the ID:
::ng-deep [id^="ngb-typeahead-"]{
width: 100%!important;
white-space: nowrap!important;
overflow: hidden!important;
text-overflow: ellipsis!important;}

Expanding on Nandita Sharma's answer, when turning off ViewEncapsulation in Angular it's probably a good idea to scope any CSS rules to the component. This will avoid generically named classes from leaking out in the global CSS scope.
A really simple way of doing that is to scope everything inside of the component's selector:
// Name of the component containing the typeahead
app-parent-selector {
// Rules added here won't leak out into the global CSS scope
.dropdown-menu {
width: 400px;
}
}
It would also be wise to avoid any approach that uses shadow-piercing descendant combinators (::ng-deep, /deep/ or >>>) because support for them is gradually being removed from all major browsers and will eventually be removed from Angular.

The best thing to do would be adding this globally, provided you plan to use the type-ahead field the same way in all your pages. If you have a styles.scss which can hold all the global styles, add this there:
ngb-typeahead-window {
width:calc(100% - 30px);
.dropdown-item {
overflow: hidden;
text-overflow: ellipsis;
}
}

Using scss should do the trick. Find the parent div in your dom, and give it a class 'dropdown-wrapper'.
.dropdown-wrapper {
.dropdown-menu {
width: 90%;
}
}
Add this to your global scss. Cheers!

Related

overriding body background color in angular 7 [duplicate]

This question already has answers here:
How to change <body> tag style from child component?
(3 answers)
Closed 2 years ago.
I have been trying to override the background body of my login and register components but it's not working
I tried adding a div with a CSS class setting its background color but the bottom part of the page isn't set to the color I picked.
I would appreciate any suggestion on the best way to solve it.
.login-page{
height: 100% !important;
background-color: #e40134 !important;
}
If you want change the class of body in some components you use ngOnInit and ngOnDestroy
//inject in the constructor the "document"
constructor(#Inject(DOCUMENT) private _document) { }
//in init you add a class to de body
ngOnInit() {
this._document.body.classList.add('new-body-class');
}
//in destroy remove the class
ngOnDestroy() {
this._document.body.classList.remove('new-body-class');
}
And
.new-body-class{
background-color: #e40134;
}
The new-body-class can be a class defined in styles.css or you can use ViewEncapsulation.None. Be Carefull, ViewEncapsulation.None makes that the .css of the componet is common to all the aplication, so if you write, e.g.
h5{color:red}
.new-body-class{
background-color: #e40134;
}
futhermore change the background, all yours h5 in your application becomes red
Use encapsulation key at #Component
import {Component, ViewEncapsulation} from "#angular/core";
#Component({
selector: 'login-page',
templateUrl: './login-page.component.html',
encapsulation: ViewEncapsulation.None
})
and use ::ng-deep in css => https://blog.angular-university.io/angular-host-context/
for example:
::ng-deep .login-page {
height: 100% !important;
background-color: #e40134 !important;
}
These are the different ways of encapsulation:
I think this is actually a problem because your has a margin by default.
So in styles.scss, I would just add this:
body: {
margin: 0
}
Try with
.login-page{
height: 100vh !important;
background-color: #e40134 !important;
}
If with this you still do not have the expected result you can add position: absolute.
In any case you can always reset the body by applying a margin: 0. It would be very helpful to know what you see if you inspect it with the browser.

ng-deep for customizing mat-tab-header causing css conflict

I have two pages and I am trying to navigate between two pages each of them has "mat-tab"
the style of the first one has:
::ng-deep.mat-tab-header {
height: 12vh;
}
the style of the second one :
::ng-deep.mat-tab-header {
height: 8vh;
}
after navigating from the second page to the first page again still the height 8vh
and I think the conflict because I am using '::ng-deep' so is there a way to change .mat-tab-header height without using '::ng-deep' ?
I'm not sure if it's customizable in that way that you need, but you can achieve that with ::ng-deep alongside with :host selector. In that way you will bound styles to your component.
For example:
:host ::ng-deep .mat-tab-header {
height: 12vh;
}
:host ::ng-deep .mat-tab-header {
height: 8vh;
}
That should solve your problem. Hope that helps.

Angular 5 Custom CSS

Hey guys so im struggling to figure out how to add custom styles to elements for different pages
If i add the styles to the global css it works.
For example i use ui-carousel on three different pages and i need them to look different on each, so global wont work for me in this case
If i put a div class in my indiviudal css pages it works fine as i can name the class.
<h3 style="margin-left: 20px;">Fotos</h3>
<p-carousel numVisible="4"
[value]="_photos">
<ng-template let-p pTemplate="p">
<p>
<img style=" width: 100%;
padding: 4px;
/* margin: auto; */
border: 1px solid #ddd;"
[src]="p.photo">
</p>
</ng-template>
</p-carousel>
Any help appreciated
Let us understand your query first -
You want to change the css styling of element or component in different places.
For this you following options -
#Input inline css
If you have just few properties you want to update then you can opt for inline css.
#Input Style Class
If you have set of themes that you want to apply on the component, then you can go with the CSS Class option as #Input
There are some more advance option like Dynamic Template but I don't think you need that.
Overwrite CSS
To overwrite css you can use :host or :host ::ng-deep
Examples :
:host >>> .ui-dropdown-item {...}
or
:host ::ng-deep .ui-dropdown-item {...}
You can see the demo in action here - https://stackblitz.com/edit/angular-wz8iq4
You can have style-sheet corresponding to each component you create. Specify which stylesheet you want to use for a component while declaring the component:
e.g.
#Component({
selector: 'your-component-selector',
templateUrl: './your-component.html',
styleUrls: ['./your-component.css']
})
You can have multiple stylesheets for a component using the styleUrls array.
Hope it helps!
I think you might need to explain your question a little bit if #alokstar's answer is not what you need, because that is how I would do it as well.
If you have a CSS file for each component, plus the global one, and you specify which stylesheet you want to use in which component, there wouldn't be a problem.
p-carousel {
<some css styling>;
}
I think this article link explains it pretty well too.
Please see this link
Apply CSS Style to child elements
Possible solution would be to apply a custom class name to each instance on a div wrapper or the element itself. You may also need to apply ::ng-deep but ultimately you need some sort of identifier to make them a unique 1:1 to the css you want to apply.
<p-carousel class="classInstance1 " numVisible="4"
p-carousel.classInstance1 .ui-carousel {
position: relative !important;
padding: 0.683rem !important;
border: none !important;
background: white !important;
}
p-carousel.classInstance2 .ui-carousel {
position: relative !important;
padding: 0.683rem !important;
border: none !important;
background: green !important;
}

Angular2 final release no longer supports :host ::shadow

I upgraded to Angular2 final release this morning and noticed that the CSS styles I was using in previous release candidates are no longer working. I need to control the look a HTML element wihtin a child component from the parent.
Here's my HTML:
<div id="intro">
<stm-video [video]="PageData.WelcomeVideo"></stm-video>
</div>
Here's my CSS:
:host ::shadow
{
stm-video
{
.video-container
{
height: 80vh;
width: inherit;
}
}
}
.video-container is a HTML element inside . I want to set the height of video-container when it's loaded in parent page. This used to work in Angular2 RC 4 and 5. Stopped working today after installing Angular2 final release.
Is there a more appropriate way to handle this?
Thank you Gunter and Clint. With your suggestions, here is what I arrived at for solving this problem (using LESS to generate CSS):
#deep: ~">>>";
:host
{
stm-video
{
#{deep}
{
.video-container
{
height: 80vh;
width: inherit;
}
}
}
}
having #{deep} directly under :host affects all child nodes, but putting it inside the child element just affects the styles within that child node (stm-video).
:host is still supported.
::shadow is not supported. As far as I know it never was.
::content is ignored.
/deep/ and >>> are equivalent and are both still supported.
:host >>> {
stm-video {
...
should do what you want.
See also Custom Styling on <ng-content> in angular2 not working ?
I think what you are looking for here is /deep/. It applies the styles down through child components. In your parent styles you would have.
/deep/ .video-container
{
height: 80vh;
width: inherit;
}

Angular2 - adding [_ngcontent-mav-x] to styles

I'm setting up a basic angular app, and I'm trying to inject some css to my views. This is an example of one of my components:
import { Component } from 'angular2/core';
import { ROUTER_PROVIDERS, ROUTER_DIRECTIVES, RouteConfig } from 'angular2/router';
import { LandingComponent } from './landing.component';
import { PortfolioComponent } from './portfolio.component';
#Component({
selector: 'portfolio-app',
templateUrl: '/app/views/template.html',
styleUrls: ['../app/styles/template.css'],
directives: [ROUTER_DIRECTIVES],
providers: [ROUTER_PROVIDERS]
})
#RouteConfig([
{ path: '/landing', name: 'Landing', component: LandingComponent, useAsDefault: true },
{ path: '/portfolio', name: 'Portfolio', component: PortfolioComponent }
])
export class AppComponent { }
Now the .css file is requested from my server, and when I inspect the page source, I can see it was added to the head. But something weird is happening:
<style>#media (min-width: 768px) {
.outer[_ngcontent-mav-3] {
display: table;
position: absolute;
height: 100%;
width: 100%;
}
.mainContainer[_ngcontent-mav-3] {
display: table-cell;
vertical-align: middle;
}
.appContainer[_ngcontent-mav-3] {
width: 95%;
border-radius: 50%;
}
.heightElement[_ngcontent-mav-3] {
height: 0;
padding-bottom: 100%;
}
}</style>
gets generated from this file:
/* Small devices (tablets, 768px and up) */
#media (min-width: 768px) {
/* center the mainContainer */
.outer {
display: table;
position: absolute;
height: 100%;
width: 100%;
}
.mainContainer {
display: table-cell;
vertical-align: middle;
}
.appContainer {
width: 95%;
border-radius: 50%;
}
.heightElement {
height: 0;
padding-bottom: 100%;
}
}
Can somebody please explain where the _ngcontent-mav tag comes from, what does it stand for and how to get rid of it?
I think this is the reason why my style is not getting applied to my templates.
If you need more info about the app structure, please checkout my gitRepo, or ask and I'll add the code to the question.
Thanks for the help.
update2
::slotted is now supported by all new browsers and can be used with `ViewEncapsulation.ShadowDom
https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted
update
/deep/ and >>> are deprecated.
::ng-deep replaces them. ::-deep is also marked deprecated in source and the docs, but this means that it will also be removed eventually.
I think it depends on what W3C comes up with for theming the shadow DOM (like https://tabatkins.github.io/specs/css-shadow-parts/)
It's basically a workaround until all browsers support that natively and ViewEncapsulation.Emulated can be removed entirely.
::ng-deep is also supported in SASS (or will be, depending on the SASS implementation)
original
View encapsulation helps to prevent styles bleeding into or out of components. The default encapsulation is ViewEncapsulation.Emulated where classes like _ngcontent-mav-x are added to component tags and also styles are rewritten to only apply to matching classes.
This emulates to some degree the default behavior of the shadow DOM.
You can disable this encapsulation adding encapsulation: ViewEncapsulation.None to the #Component() decorator.
Another way is the recently (re-)introduced shadow piercing CSS combinators >>>, /deep/, and ::shadow. These combinators were introduced for styling shadow DOM but are deprecated there. Angular introduce them recently until other mechanisms like CSS variables are implemented.
See also https://github.com/angular/angular/pull/7563 (https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta10-2016-03-17)
>>> and /deep/ are equivalent and using this combinators makes the styles ignore the the added helper classes (_ngcontent-mav-x)
* >>> my-component, /* same as */
* /deep/ my-component {
background-color: blue;
}
applies to all my-component tags not matter how deep they are nested in other components.
some-component::shadow * {
background-color: green;
}
applies to all elements in the template of some-component, but not further descendants.
They can also be combined
* /deep/ my-component::shadow div {
background-color: blue;
}
this applies to all div elements in the template of all my-component templates no matter how deep my-component is nested in other components.
/deep/, >>>, and ::shadow can only be used with
encapsulation: ViewEncapsulation.None
encapsulation: ViewEncapsulation.Emulated
encapsulation: ViewEncapsulation.Native when the browser supports them natively (Chrome does but prints a warning in the console that they are deprecated) or
when the browser doesn't native support shadow DOM and the
web_components polyfills are loaded.
For a simple example see also the Plunker from this question https://stackoverflow.com/a/36226061/217408
See also this presentation from ng-conf 2016 https://www.youtube.com/watch?v=J5Bvy4KhIs0
You should try this,
import {ViewEncapsulation} from 'angular2/core';
#Component({
...
encapsulation: ViewEncapsulation.None,
...
})

Resources