npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@myrmidon/cadmus-ui-flags-picker

v5.1.0

Published

Cadmus - flags picker component.

Downloads

140

Readme

CadmusUiFlagsPicker

This library was generated with Angular CLI version 17.3.0.

The flags picker allows to select 1 or more flags (i.e. entries which are either present or absent) from a list. Each flag has a string ID and a human-friendly label, and implements interface Flag. Optionally users can add new flags to the list.

API

Each flag has:

  • id: the ID for this flag.
  • label: the human-friendly label for this flag.
  • user: optionally set to true when this flag was added by user.

Component's properties:

  • flags: the flags.
  • numbering: true to show an ordinal number next to each flag.
  • toolbar: true to show the toolbar including quick selection buttons and the UI for adding new flags.
  • allowUserFlags: true to allow users add new flags.

Component's events:

  • flagsChange: emitted when flags have changed.

Adapter

A typical usage scenario for this brick in Cadmus is providing a multiple-selection list of entries from a thesaurus. In this case, you can take advantage of the FlagsPickerAdapter, which is designed for a scenario where:

  • your component has any number of flags sets to handle, each fed by a thesaurus.
  • you cannot determine the order in which the flags or their check states are set by the host component into the flags brick component. So, it might happen that flags definitions from thesauri are set first, and then their checked states are updated from the model being edited; or vice-versa. You thus need a way of allowing any order while keeping this information in synch.

The adapter sits between the flags brick and its consumer. The brick's flags property is bound to an observable got from the adapter for a specific set of flags; and the flagsChange event handler notifies the adapter of user changes via setSlotFlags. In turn, the consumer component sets the available flags and their initial checked states, usually drawing the former from a thesaurus and the latter from the model it handles.

The typical procedure for using an adapter is illustrated below. It assumes that:

  • you have 1 or more flags set, each fed by a thesaurus.
  • you save the flags in a form's control. As for the adapter, this is redundant, because the adapter already keeps track of flags; yet, it's often useful to have a form's control representing the flags, to correctly handle dirty state and validation. So, we just save the flags also in this control, when present.

(1) just to save some typing, create an adapter function to convert thesaurus entries to flags:

function entryToFlag(entry: ThesaurusEntry): Flag {
  return {
    id: entry.id,
    label: entry.value,
  };
}

(2) add a readonly flags adapter member to your component, and a ...Flags$ observable property for each flags set:

private readonly _flagAdapter: FlagsPickerAdapter;

// flags
public stateFlags$: Observable<Flag[]>;

// in constructor:
// flags
this._flagAdapter = new FlagsPickerAdapter();
// TODO: instantiate each set of flags using a key ID, e.g.:
this.stateFlags$ = this._flagAdapter.selectFlags('states');

(3) in your entries property setter, use the adapter to set the corresponding flags, e.g.:

// cod-content-states
@Input()
public get stateEntries(): ThesaurusEntry[] | undefined {
  return this._stateEntries;
}
public set stateEntries(value: ThesaurusEntry[] | undefined) {
  if (this._stateEntries === value) {
    return;
  }
  this._stateEntries = value || [];
  this._flagAdapter.setSlotFlags(
    'states',
    this._stateEntries.map(entryToFlag)
  );
}

(4) if you want to let the form properly handle dirty state and validation, in your form have a control for the flags, e.g. public states: FormControl<Flag[]>, and instantiate it as any other form item.

(5) in your updateForm function, set the flag IDs via the adapter. Note that we deal only with the adapter, as the control will be automatically set when the flags brick fires back its flags change event. Anyway, you might want to update the control also at this stage if your form depends on it not only for change detection, but also for validation:

// update form
this._flagAdapter.setSlotChecks('states', content.states);

// or, if you need to have your form's control initialized:
this.states.setValue(this._flagAdapter.setSlotChecks('states', content.states));

(6) conversely, in your getModel function, get the IDs of the checked flags from the adapter:

// get model
// ...
states: this._flagAdapter.getOptionalCheckedFlagIds('states'),

The getFlagIds and getOptionalFlagIds methods are used to extract the IDs of the checked flags only, returning an array which is empty when no flag is checked, or undefined, according to the method called.

(7) handle the flagsChange event from the flags component to update the form's control. Note that when we receive a change event from the brick control, we need to update both the checked states for the flags, and the flags themselves, as there might be user-defined flags. So we are using the adapter's setSlotFlags method with a true parameter to tell it that the checked states must be drawn from the received flags, rather than extracted from the existing slot in the adapter:

public onStateFlagsChange(flags: Flag[]): void {
  this._flagAdapter.setSlotFlags('states', flags, true);
  this.states.setValue(flags);
  this.states.markAsDirty();
  this.states.updateValueAndValidity();
}

(8) in your component's template, the flags component is used like:

<cadmus-ui-flags-picker
  [flags]="stateFlags$ | async"
  (flagsChange)="onStateFlagsChange($event)"
></cadmus-ui-flags-picker>