Skip to content

Latest commit

 

History

History
136 lines (94 loc) · 5.1 KB

README.md

File metadata and controls

136 lines (94 loc) · 5.1 KB

JS Guide

Import Order

When importing dependencies we loosely follow some general rules and strictly follow others. The canonical ordering list lives in /AGENTS.md; this is the worked example.

// 3rd party dependencies generally in order or "lowest-level" dependency
import { extend } from 'underscore';
import hbs from 'handlebars-inline-precompile'; // not really a dependency, but indirectly used by Marionette
import { View } from 'marionette';

// General css goes next before any local imports
import 'scss/modules/global.scss';

// Utilities
import funFormatter from 'js/utils/fun-formatter';

import intl from 'js/i18n';

// Base classes
import App from 'js/base/app';

// Entities and service modules
import { Model as PatientModel } from 'js/entities-service/entities/patients';

// Apps (typically alphabetically)
import ChildApp from 'js/apps/foo/child/child_app';
import LocalDepApp from './local_app';

// Other Mn classes in no particular order (there's usually not many)
import FooBehavior from 'js/behaviors/foo';
import FooRegion from 'js/regions/foo';
import FooComponent from 'js/components/foo';

// Views (typically alphabetically)
import { FooView, BarCollectionView } from 'js/apps/foo/child/child_views';
import { LocalDepView } from './local_views';

// Structural templates; leaf templates are typically inlined with hbs``
import FooTemplate from './foo.hbs';

// App-shared and cross-app domain css come after dependencies that may import styles
import 'js/apps/foo/shared/foo.scss';
import 'scss/domain/foo.scss';

// Local css
import './for-this-view.scss';

Handlebars Templates

Keep a template inline when it is a leaf fragment that makes the view easier to understand beside its behavior. Typical examples include button contents, icons, labels, status values, empty messages, and small picklist items with shallow conditional rendering.

Use a colocated .hbs file when the template defines structure that is meaningful independently of the view behavior. Page and application layouts, list rows, result items, loading skeletons, multi-region views, editor bodies, and members of an existing template family generally belong in files.

Template length is only a signal. Long attributes and translation keys do not make a cohesive leaf fragment structural, while a short template that defines a page's region topology may still deserve a file. Do not introduce a shared or configurable template merely because two views currently have similar markup; extracting a template file is separation, not abstraction.

Import Aliases

Rather than needing to import files relatively, by resource asset directories are aliased with vite. The aliases can be found here: https://github.com/RoundingWell/app-frontend/blob/develop/vite.config.js

These aliases allow for any js file, no matter its location within the js directory to import like so:

import { FooView } from 'js/apps/foo/foo_views';

Marionette

See AGENTS.md for this app's installed contract, integrations, ownership entrypoint, and packaged documentation helper. Use the marionette skill supplied by Marionette's upstream plugin to select the matching framework API guide for the task.

This repo requires template element selectors in the View's ui hash and access through getUI, keeping selector queries out of View methods. The packaged docs/dom.interactions.md explains the native DOM values and event APIs.

Trigger and Event Names

All trigger and event names should be wrapped in ''.

Incorrect way:

trigger:something:happened: this.onSomethingHappened

Correct way:

'trigger:something:happened': this.onSomethingHappened

Events should alway indicate something that happened and not an action to take. Ideally named verb:name like click:fooButton or sometimes context:verb:name like state:change:foo. Ideally handlers also indicate handling the event rather than a specific action. Particularly if an event handler does more than one thing.

Object Keys

Should not be wrapped in ''. For example:

Incorrect way:

const x = {
  'foo':'bar',
  'bar':'foo'
};

Correct way:

const y = {
  foo: 'bar',
  bar: 'foo'
};

Note: Our linter currently cannot lint this.

General Best Practices