fix(angular): tabs supports conditional slot bindings (#27582)

Issue number: Resolves #19484

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

The Angular implementation of `ion-tabs` does not support conditional
binding the `slot` property on `ion-tab-bar` or assigning a variable as
the slot.

For example, this usage is invalid:

```html
<ion-tabs>
  <ion-tab-bar [slot]="slot"></ion-tab-bar>
</ion-tabs>
```

This occurs because `ng-content` only supports static content
projection. It is not intended for scenarios where the content can be
relocated or conditionally rendered.

An example of static content projection would be:
```html
<ion-tabs>
  <ion-tab-bar slot="top"></ion-tab-bar>
</ion-tabs>
```

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- `ion-tabs` supports conditional slot bindings or a slot that is bound
to a variable in Angular.

The revised implementation relocates the tab bar in the `ion-tabs`
template, based on it's current slot attribute. The implementation
checks the tab bar slot whenever the content changes.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Dev-build: `7.0.11-dev.11685631370.18980633`

---------

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
This commit is contained in:
Sean Perkins
2023-06-06 22:41:33 -04:00
committed by GitHub
parent f2c1845fba
commit d20bea561c
4 changed files with 136 additions and 5 deletions

View File

@@ -435,6 +435,30 @@ describe('Tabs', () => {
})
})
it('Tabs should support conditional slots', () => {
cy.visit('/tabs-slots');
cy.get('ion-tabs .tabs-inner + ion-tab-bar').should('have.length', 1);
// Click the button to change the slot to the top
cy.get('#set-slot-top').click();
// The tab bar should be removed from the bottom
cy.get('ion-tabs .tabs-inner + ion-tab-bar').should('have.length', 0);
// The tab bar should be added to the top
cy.get('ion-tabs ion-tab-bar + .tabs-inner').should('have.length', 1);
// Click the button to change the slot to the bottom
cy.get('#set-slot-bottom').click();
// The tab bar should be removed from the top
cy.get('ion-tabs ion-tab-bar + .tabs-inner').should('have.length', 0);
// The tab bar should be added to the bottom
cy.get('ion-tabs .tabs-inner + ion-tab-bar').should('have.length', 1);
});
function testTabTitle(title) {
const tab = getSelectedTab();

View File

@@ -57,6 +57,10 @@ const routes: Routes = [
path: 'tabs-global',
loadChildren: () => import('./tabs-global/tabs-global.module').then(m => m.TabsGlobalModule)
},
{
path: 'tabs-slots',
loadComponent: () => import('./tabs-slots.component').then(c => c.TabsSlotsComponent)
},
{
path: 'nested-outlet',
component: NestedOutletComponent,

View File

@@ -0,0 +1,32 @@
import { Component } from "@angular/core";
import { IonicModule } from "@ionic/angular";
/**
* Test purpose: Validates that the tab bar is relocated to the
* correct location when the slot attribute changes or is bound
* to a variable.
*/
@Component({
selector: 'app-tabs-slots',
template: `
<ion-tabs>
<ion-tab-bar [slot]="slot"></ion-tab-bar>
</ion-tabs>
<ion-fab vertical="bottom" horizontal="end">
<button id="set-slot-top" (click)="setSlot('top')">Slot - top</button>
<br />
<button id="set-slot-bottom"(click)="setSlot('bottom')">Slot - bottom</button>
</ion-fab>
`,
imports: [IonicModule],
standalone: true
})
export class TabsSlotsComponent {
slot?: string;
setSlot(newSlot: string) {
this.slot = newSlot;
}
}