Zerok
Zerok

Reputation: 1503

Partial accordion-style animation on Angular component with various templates

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:

enter image description here

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:

enter image description here

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>
              &nbsp;|&nbsp;  
            {{ 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:

Upvotes: 0

Views: 1551

Answers (1)

Gautam
Gautam

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

Related Questions