-
-
Notifications
You must be signed in to change notification settings - Fork 6
Open
Description
Here is the functionality with detailed comment that I would add to signals library. It solves the problem when I want to connect separate components on the page through signals, but I do not want one component to update all instances of another one which is dependent through signals. instead I would create channel based signal and would change signal for specific channel, to update only specific instances of dependent components
/**
* Initializes a channel-based signal manager that enables isolated reactive state
* management across multiple named channels. Each channel holds an independent signal,
* allowing decoupled control for components sharing common logic.
*
* Example usage:
* const mySignal = $channelSignal();
* mySignal.setForChannel('PageChannel1', true);
* const current = mySignal.forChannel('PageChannel1');
*
* This is particularly useful for generic components—like pagination—that rely on reactive state.
* Consider a scenario where multiple paginated tables are rendered on the same page:
*
* With a single signal:
* const pageNumber = $signal(1);
*
* Every pagination instance would trigger updates across all tables via a shared effect:
* $effect(() => {
* if (pageNumber.value !== this.pageNumber) {
* this.pageNumber = pageNumber.value;
* }
* this.fetchCurrentPage();
* });
*
* Replacing it with a channel-based signal isolates each table’s pagination:
* const pageNumber = $channelSignal();
*
* Each Pagination component assigns its own channel:
*
* export default class Pagination {
* @api channel;
*
* setPage(event) {
* pageNumber.setForChannel(this.channel, event.detail.value);
* }
* }
*
* export default class GenericTable {
* @api channel;
* pageNumber;
*
* connectedCallback() {
* $effect(() => {
* this.pageNumber = pageNumber.forChannel(this.channel).value;
* this.fetchCurrentPage();
* });
* }
* }
*
* This approach prevents unwanted cross-updates and keeps component state scoped to its context.
*
* @function
* @returns {Object} An object containing `forChannel` and `setForChannel` methods
* for managing per-channel signals.
*
* @property {Function} forChannel - Retrieves or initializes a signal for a given channel.
* @param {string} channel - The channel identifier.
* @param {*} [defaultValue] - Initial value if the signal is newly created.
* @param {Object} [options] - Optional signal configuration.
* @returns {*} The signal linked to the provided channel.
*
* @property {Function} setForChannel - Updates the signal value for a specified channel.
* @param {string} channel - The target channel name.
* @param {*} value - New value to assign.
* @param {Object} [options] - Optional signal configuration.
*/
function $channelSignal() {
return {
forChannel: function(channel, defaultValue, options) {
if (!this[channel]) {
this[channel] = $signal(defaultValue ?? undefined, options);
}
return this[channel];
},
setForChannel: function(channel, value, options) {
if (!this[channel]) {
this[channel] = $signal(value, options);
} else {
this[channel].value = value;
}
}
};
}
cesarParra
Metadata
Metadata
Assignees
Labels
No labels