mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 20:33:32 +08:00
refactor(segment): link the button and content with content-id and id
This commit is contained in:
@ -4,6 +4,8 @@
|
||||
:host {
|
||||
display: flex;
|
||||
|
||||
height: 100%;
|
||||
|
||||
overflow-x: scroll;
|
||||
scroll-snap-type: x mandatory;
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import type { ComponentInterface } from '@stencil/core';
|
||||
import { Component, Element, Host, Listen, h } from '@stencil/core';
|
||||
import { addEventListener, removeEventListener } from '@utils/helpers';
|
||||
import { Component, Element, Host, Listen, Method, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-segment-view',
|
||||
@ -8,76 +7,59 @@ import { addEventListener, removeEventListener } from '@utils/helpers';
|
||||
shadow: true,
|
||||
})
|
||||
export class SegmentView implements ComponentInterface {
|
||||
private segmentEl: HTMLIonSegmentElement | null = null;
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
@Listen('scroll')
|
||||
segmentViewScroll(ev: any) {
|
||||
const { segmentEl } = this;
|
||||
handleScroll(ev: any) {
|
||||
const { scrollLeft, offsetWidth } = ev.target;
|
||||
const atSnappingPoint = scrollLeft % offsetWidth === 0;
|
||||
|
||||
const atSnappingPoint = ev.target.scrollLeft % ev.target.offsetWidth === 0;
|
||||
if (!atSnappingPoint) return;
|
||||
|
||||
if (atSnappingPoint) {
|
||||
const index = Math.round(ev.target.scrollLeft / ev.target.offsetWidth);
|
||||
const segmentButton = this.getSegmentButtonAtIndex(index);
|
||||
const index = Math.round(scrollLeft / offsetWidth);
|
||||
const segmentContent = this.getSegmentContentAtIndex(index);
|
||||
|
||||
if (segmentEl) {
|
||||
segmentEl.value = segmentButton.value;
|
||||
}
|
||||
if (segmentContent === null || segmentContent === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const segmentButton = this.getSegmentButtonById(segmentContent.id) as HTMLIonSegmentButtonElement;
|
||||
const segment = this.getParentSegment(segmentButton);
|
||||
|
||||
if (segment) {
|
||||
segment.value = segmentButton.value;
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const segmentEl = (this.segmentEl = document.querySelector(`ion-segment[view=${this.el.id}]`));
|
||||
if (segmentEl) {
|
||||
addEventListener(segmentEl, 'ionChange', this.updateSection);
|
||||
}
|
||||
}
|
||||
@Method()
|
||||
async setContent(id: string) {
|
||||
const contents = this.getSegmentContents();
|
||||
const index = contents.findIndex((content) => content.id === id);
|
||||
|
||||
disconnectedCallback() {
|
||||
const segmentEl = this.segmentEl;
|
||||
if (segmentEl) {
|
||||
removeEventListener(segmentEl, 'ionChange', this.updateSection);
|
||||
this.segmentEl = null;
|
||||
}
|
||||
}
|
||||
if (index === -1) return;
|
||||
|
||||
private updateSection = () => {
|
||||
const { segmentEl } = this;
|
||||
|
||||
if (segmentEl) {
|
||||
const value = segmentEl.value;
|
||||
const index = this.getSegmentButtonIndexWithValue(value);
|
||||
this.setSection(index);
|
||||
}
|
||||
};
|
||||
|
||||
private setSection = (index: number) => {
|
||||
const sectionWidth = this.el.offsetWidth;
|
||||
const contentWidth = this.el.offsetWidth;
|
||||
this.el.scrollTo({
|
||||
top: 0,
|
||||
left: index * sectionWidth,
|
||||
left: index * contentWidth,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
private getSegmentButtons(): HTMLIonSegmentButtonElement[] {
|
||||
const { segmentEl } = this;
|
||||
|
||||
if (!segmentEl) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Array.from(segmentEl.querySelectorAll('ion-segment-button'));
|
||||
}
|
||||
|
||||
private getSegmentButtonAtIndex(index: number) {
|
||||
return this.getSegmentButtons()[index];
|
||||
private getSegmentContents(): HTMLIonSegmentContentElement[] {
|
||||
return Array.from(this.el.querySelectorAll('ion-segment-content'));
|
||||
}
|
||||
|
||||
private getSegmentButtonIndexWithValue(value: any) {
|
||||
return this.getSegmentButtons().findIndex((b) => b.value === value);
|
||||
private getSegmentContentAtIndex(index: number) {
|
||||
return this.getSegmentContents()[index];
|
||||
}
|
||||
|
||||
private getSegmentButtonById(id: string) {
|
||||
return document.querySelector(`ion-segment-button[content-id="${id}"]`);
|
||||
}
|
||||
|
||||
private getParentSegment(button: Element) {
|
||||
return button.closest('ion-segment');
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -12,37 +12,56 @@
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
|
||||
<style>
|
||||
ion-segment-view {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
ion-segment-content:nth-of-type(even) {
|
||||
background: lightblue;
|
||||
}
|
||||
|
||||
ion-segment-content:nth-of-type(odd) {
|
||||
background: lightpink;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body onload="listenForEvent()">
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Segment View - Basic</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-toolbar>
|
||||
<ion-segment view="myView" value="Paid">
|
||||
<ion-segment-button value="Paid">
|
||||
<ion-segment value="Paid">
|
||||
<ion-segment-button content-id="paid" value="Paid">
|
||||
<ion-label>Paid</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="Free">
|
||||
<ion-segment-button content-id="free" value="Free">
|
||||
<ion-label>Free</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="Top">
|
||||
<ion-segment-button content-id="top" value="Top">
|
||||
<ion-label>Top</ion-label>
|
||||
</ion-segment-button>
|
||||
</ion-segment>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-segment-view id="myView">
|
||||
<ion-segment-content> Paid </ion-segment-content>
|
||||
<ion-segment-content> Free </ion-segment-content>
|
||||
<ion-segment-content> Top </ion-segment-content>
|
||||
<ion-segment-view>
|
||||
<ion-segment-content id="paid">Paid</ion-segment-content>
|
||||
<ion-segment-content id="free">Free</ion-segment-content>
|
||||
<ion-segment-content id="top">Top</ion-segment-content>
|
||||
</ion-segment-view>
|
||||
</ion-content>
|
||||
|
||||
<ion-footer>
|
||||
<ion-toolbar>
|
||||
<ion-title>Footer</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-footer>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user