Angular: How to change child element height - css

Currently I have a layout like so
<parent-comp>
<child1> </child1>
<child2> </child2>
</parent-comp>
Parent component have fixed height ( 1000px )
Child 1 have 2 states: Expanded( 200px ) and Collapsed( 10px )
I would like to use these information to calculate and update child2's height accordingly
I do not want to set child2's height to auto ( I need a specific value since this is the requirement to pass it into another library (the virtual scroll) )
How can I achieve this?
I tried ViewChild + ElementRef to get child component's height from parent component but it seems to cause ExpressionChangedAfterItHasBeenCheckedError when I try to update the child component's height
Should the child component output it's current height to the parent or the parent should read it from it's child?

instead of doing it the hard way, you can simply use flex-box, which would take care of doing all the calculations for you.
e.g
.parent {
display:Flex;
flex-direction:column;
flex-wrap:wrap;
height: 1000px;
}
.child1 {
/* expanded */
flex: 0 0 20%;
}
.collapsed {
flex: 0 0 2%;
}
.child2 {
flex: 1;
}
you can apply collapsed classed dynamically with the help of ngclass, hope this helps.
If you want to learn more about flexbox play these free game at https://flexboxfroggy.com/ Hope this helps.

Yes, you're right. You need to Output the value from child to parent and propagate it to desired components and do your calculations.
Here's an example.
If you want to pass this change of height to Components other than the children then I would suggest you use a SharedService to subscribe and make changes to the value(s). Siblings or not, this way you can share data between multiple components.
If you just want to update the height, using Flexbox or Grids is a better alternative.

Related

css math functions backwards compatibility

When using the following css selector on a toolbar to require a minimum bottom margin, it causes the toolbar height to be 0 on Chrome 59:
.toolbar {
height: calc(var(--f7-toolbar-height) + max(var(--f7-safe-area-bottom), 10px));
}
I tried the following, hoping Chrome 59 would only use the first height definition:
height: calc(var(--f7-toolbar-height) + var(--f7-safe-area-bottom));
height: calc(var(--f7-toolbar-height) + max(var(--f7-safe-area-bottom), 10px));
But Chrome 59 still uses only the second height definition which results in 0 height.
The following also doesn't work:
#supports(height: max(0px)) {
height: calc(var(--f7-toolbar-height) + max(var(--f7-safe-area-bottom), 10px));
}
It still tries to apply the height, and causes 0 height.
Is there a backwards compatible way to achieve this height? It would be fine if Chrome 59 simply ignored the height and inherit it from somewhere else, as long as it doesn't cause a 0 height.
The following approach works:
&.supports-css-math {
height: calc(var(--f7-toolbar-height) + max(var(--f7-safe-area-bottom), 10px));
}
And then in javascript, that supports-css-math class needs to be added. If using react or vue, it can be added in the component's template.
Another approach that might be better, but haven't tried yet, would be to add the supports-css-math at the top of the dom, and then define a css variable based on the selector, e.g., --min-toolbar-bottom, which can later be used in the toolbar component.

how to use angular material form field and flex-layout

I want to have 2 form input fields in one row:
1. the first has a fixed with,
1. the second should grow and shrink, but this does not shrink below 180px.
Here is a full stack-blitz example
When you start the app, we see this
There maybe another issue:
I think the 2nd input field should already show the hint text and the horizontal line - but it will only show it when it get's the focus.
Is this the expected behaviour or am I missing something?
Anyway. The main issue is that the 2nd field does not shrink as expected. It will not shrink below 180px:
In the chrome dev-tool I can see that the input element is wrapped with a div class="mat-form-field-infix"> and the class mat-form-field-infix has a fixed width of 180px!
The only workaround that I came up with is to override this width with using ::ng-deep.
You can activate this in the co-input-field.component.scss file of the Stackblitz example
:host ::ng-deep .mat-form-field-infix {
// width: auto !important;
width: unset !important;
}
With this workaround the 2nd input shrinks as expected:
But ::ng-deep is deprecated and will be removed.
So what is the right way to make the input shrink as expected?
since .mat-form-field-infix has a fixed width of 180px there is no way of making form field shrink beyond 180px. inevitably .mat-form-field-infix must be overridden.
you can achive the same result with ::ng-deep in a couple of ways;
1.disable view encapsulation for that particular component. However, this approach has a huge drawback that all the styles in your component becomes global so they need to be managed carefully.
#Component({
selector: 'app-co-input-field',
templateUrl: './co-input-field.component.html',
styleUrls: ['./co-input-field.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class CoInputFieldComponent {}
and then in co-input-field.component.scss you do the following
app-co-input-field {
.mat-form-field-infix {
width: auto !important;
}
// all other component styles goes in here
// in order to keep them isolated from global scope
}
2.don't disable view encapsulation. use the element selector of parent component in global styles.
put the following in styles.scss
app-co-input-field {
.mat-form-field-infix {
width: auto !important;
}
// co-input-field.component.scss still can be used for encapsulated styles
}
3.don't disable view encapsulation. define a global rule for this particular situation.
put the following in styles.scss
.shrinking-mat-form-field {
.mat-form-field-infix {
width: auto !important;
}
}
and apply the .shrinking-mat-form-field class to corresponding element
<mat-form-field style="width: 100%" class="shrinking-mat-form-field">
<input matInput placeholder="placeholder" />
<mat-hint align="end">hint text</mat-hint>
</mat-form-field>
Even though second and third approaches are fundamentally same I personally prefer the third approach in order to make it readable, keep it consistent over the project, have minimal side effects and manage them from a single point.
:host ::ng-deep.mat-form-field-appearance-legacy .mat-form-field-infix {
padding: 0.4375em 0;
display: flex;
}

Hide Polymer element

i try to hide several polymer elements on a certain element condition. I'm aware that there are several possibilities. In my opinon the easiest way to do this is to introduce a new CSS class
.invisible {
display: none;
}
and add it to the class list of the polymer elements
this.$.icon.classList.add('invisible');
this.$.text.classList.add('invisible');
this.$.button.classList.add('invisible');
But this has no effect on the elements. The elements are still visible. A look into the elment inspector shows, that the class was added:
class="style-scope parent-elem invisible"
Where parent-elem is the name of the parent element.
Can anyone explain me why the element will not be hidden?
Thank you
Best Regards,
Meisenmann
you can easly manipulate on your elements with parent property. Try in your element properties add property
properties: {
...
elementsVisible: {
type: Boolean,
value: true
}
...
}
then in your method manipulate this property and in html component set
<element hidden="[[!elementsVisible]]" ></element>
ps. if this wont work you can add in parent css
[hidden] {
display: none;
}
sometimes polymer elements need special mixins to customize their css, but hidden usually works :)

Can I set width of jQuery's split button

At this URL ( http://jqueryui.com/demos/button/#splitbutton ) you can see what I mean for splitbutton.
I would set the width of first button (the one which contain text). There is a way to do this?
In you CSS, you should include this:
.ui-button-text {
width: 300px;
}
Or to whatever the desired width is.

static pages that dont break?

Hi I want to do a fixed size page, but don't want the page to break or reflow at all if the user resizes the window. Is this a javascript function?
sample: http://www.neimanmarcus.com/
Most people put all the content of there page inside a div with an id, such as 'doc', then they would apply the following rule:
<body><div id="doc">
YOUR PAGE HERE
</div></body>
body {
test-align: center;
}
#doc {
margin: 0 auto;
text-align: left;
width: 940px
}
The "text-align" fixes an IE 6 issue, really you just need to assign a margin to your wrapping document div.
it doesn't need java script function .
but remember : don't use % for declaring width or height for elements in css.(for having a static element that resizing window doesn't effect that).
for example : "width:90%;" ==> replace this with "width:100px;"

Resources