@@ -28,8 +28,43 @@ const chipSet = document.querySelector<MdChipSet>('#chips');
28
28
if ( ! chipSet ) {
29
29
throw new Error ( `Internal Error: no filter chips rendered` ) ;
30
30
}
31
- chipSet . addEventListener ( 'click' , async ( ) => {
32
- await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) ) ; // Wait for filter chips to be completely updated.
31
+
32
+ /**
33
+ * Updates the URL Hash based on the current state of the filter chips. If all
34
+ * chips on the page are selected, then clears the hash.
35
+ */
36
+ const updateUrlFromChips = ( ) => {
37
+ const chips = Array . from ( chipSet . chips as FilterChip [ ] ) ;
38
+ let allSelected = true ;
39
+ const filters = [ ] ;
40
+
41
+ for ( const chip of chips ) {
42
+ if ( chip . selected ) {
43
+ filters . push ( chip . dataset . value ! ) ;
44
+ } else {
45
+ allSelected = false ;
46
+ }
47
+ }
48
+
49
+ // Save it as a query param in the hash to prevent page reload
50
+ const queryParams = new URLSearchParams ( window . location . hash . slice ( 1 ) ?? '' ) ;
51
+ if ( allSelected ) {
52
+ queryParams . delete ( 'filter' ) ;
53
+ } else {
54
+ queryParams . set ( 'filter' , filters . join ( ',' ) ) ;
55
+ }
56
+
57
+ window . location . hash = queryParams . toString ( ) ;
58
+ } ;
59
+
60
+ const updateContentFromChips = async ( updateHash = true ) => {
61
+ // Wait for filter chips to be completely updated.
62
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) ) ;
63
+
64
+ if ( updateHash ) {
65
+ updateUrlFromChips ( ) ;
66
+ }
67
+
33
68
const keepKinds = new Set (
34
69
( chipSet . chips as FilterChip [ ] )
35
70
. filter ( ( el ) => el . selected )
@@ -44,4 +79,40 @@ chipSet.addEventListener('click', async () => {
44
79
card . style . display =
45
80
keepKinds . has ( cardKind ) || cardKind === 'always-show' ? 'flex' : 'none' ;
46
81
}
82
+ } ;
83
+
84
+ /**
85
+ * Initialize the filter chips based on the URL hash.
86
+ */
87
+ const initChipsFromURL = async ( hash = window . location . hash ) => {
88
+ const queryParams = new URLSearchParams ( hash . slice ( 1 ) ?? '' ) ;
89
+ const kinds = Array . from ( queryParams . get ( 'filter' ) ?. split ( ',' ) ?? [ ] ) ;
90
+
91
+ chipSet . chips . forEach ( async ( chip ) => {
92
+ // Wait for filter chips to be completely updated to not compete with SSR.
93
+ await chip . updateComplete ;
94
+ const chipKind = chip . dataset . value ! ;
95
+ ( chip as FilterChip ) . selected =
96
+ kinds . length === 0 || kinds . includes ( chipKind ) ;
97
+ } ) ;
98
+ } ;
99
+
100
+ // Handles forwads and back navigation between hashes
101
+ window . addEventListener ( 'hashchange' , async ( event : HashChangeEvent ) => {
102
+ await initChipsFromURL ( new URL ( event . newURL ) . hash ) ;
103
+ // Do not update hash to prevent an infinite loop.
104
+ await updateContentFromChips ( false ) ;
47
105
} ) ;
106
+
107
+ // Handles clicking a filter chip.
108
+ chipSet . addEventListener ( 'click' , ( ) => updateContentFromChips ( ) ) ;
109
+
110
+ const isChipDefined = ! ! customElements . get ( 'md-filter-chip' ) ;
111
+
112
+ if ( ! isChipDefined ) {
113
+ // Wait for SSR hydration to complete before initializing the chips.
114
+ customElements . whenDefined ( 'md-filter-chip' ) . then ( ( ) => initChipsFromURL ( ) ) ;
115
+ } else {
116
+ // Hydration has completed, initialize the chips immediately.
117
+ initChipsFromURL ( ) ;
118
+ }
0 commit comments