Reputation: 1503
I'm making a production app that has a card-style layout. Every filter (date pickers, etc) and visualizers (table, chart) is wrapped inside a "Card" component. There are even two child components that inherit from this class.
So in the end, this is how a pair of cards look, so you can have an idea on what's going on:
As you can see, the cards have 3 parts:
The requisite we currently have, is to be able to click in the chevron (that icon in the card header right), and hide just the inner component. This is the result I want to achieve:
But I'm having a problem with this, because of how I designed these cards. Look at how the card code parent class looks:
@Component({
selector: "card",
styleUrls: ["./card.css"],
template: `
<div class="col card" [@animate]="enabled">
<div class="row card-header">
{{title}}
<i (click)="switchVisibility()" class="fa fa-chevron-down icon-right"></i>
</div>
<div class="margin" [@animate2]="enabled">
<ng-content></ng-content>
</div>
`
Implementation:
<card [title]="'DATE SELECT'" class="col">
<date-picker-wrapper class="date-wrapper" [config]="config" [dateranges]="dateranges" [doubleDateRange]="false">
</date-picker-wrapper>
</card>
You probably have already spotted one of the problems here: all of the inner component is inserted in the ng-content, therefore, if I hide the component with an animation located at the Card (which is the idea, so I can inherit this method in the child card classes)... I will hide the footer too. And that's not the plan.
I guess I need to wrap inside the ng-content the upper side template, and the footer in another different template or something. But I don't know how to do it, and the guides regarding ng-template didn't seem to be very clear. Also, I'm not very sure of what's the best approach to achieve this result.
This is how a component's footer looks, in this case, the daterangepicker:
<div class="footer-component">
<hr>
<p class="footer-text">
<span style="color:#ff8716;">
{{ config?.daterange?.rangelabel ? config?.daterange?.rangelabel : "Custom" }}
</span>
|
{{ getFormattedDate(1, true) }} - {{ getFormattedDate(1, false) }}
</p>
<button class="btn btn-relocator" (click)="openDate(datemodal)">Edit</button>
</div>
One of the problems I see here, is that this footer actually requires some functionality of the component, some methods that are not global and therefore, not accessible from outside of the component.
Then, I've got a few questions:
Should I replicate this animation in all my components, inside their template? Wouldn't that be a little bit dirty? How would you populate the state of the chevron icon click to the inner component?
If there is a way of inserting two templates in the Card component, how do you think I can access the component's logic from the footer template?
Any comments regarding how I should "hide" the content? I've got an idea using "*" height as for "auto", but I'm not sure if that even works.
Upvotes: 0
Views: 1551
Reputation: 238
For hiding the , you need to use a boolean toggle variable. In your component, declare variable as below:- enabledContent = false; Then try to modify your html like below:-
<div class="col card" [@animate]="enabled">
<div class="row card-header">
{{title}}
<i (click)="enabledContent=!enabledContent;switchVisibility();" class="fa fa-chevron-down icon-right"></i>
</div>
<div class="margin" [@animate2]="enabledContent">
<ng-content></ng-content>
</div>
Click on this for sample code because I am not aware [@anumate2], in sample link it is [hidden] .
For enable a method global, you may achieve by doing below step:-
First create a service, myservice.service.ts and inside write your function(sample code showing only):-
public getFormattedDate(1, true): any {
return result;
}
Now in your component , declare your service as below(sample code showing only):-
import { Component, OnInit,} from '@angular/core';
import { MyService} from './myservice.service';
@Component({ selector: ... templateUrl: ... styleUrls: ... })
export class MyComponent implements OnInit {
constructor(private myservice: Myservice) { }
ngOnInit() { }
}
Then in your html file, use your service method as below(sample code showing only):-
<div class="footer-component">
{{ myservice.getFormattedDate(1, true) }} - {{ myservice.getFormattedDate(1, false) }}
</div>
I tried to use variable from a service.ts inside html file, it works fine, but I haven't tested calling method from service.ts. Hope it will work. If it is ok, then you can call your service method from anywhere as services are global in angular and just need to declare in component to be used.
Upvotes: 1