Skip to content

Commit

Permalink
Adds actions to components
Browse files Browse the repository at this point in the history
Actions add additional functionality to elements within your component's template that may be difficult to add with other mechanisms. Examples of functionality which actions makes trivial to attach are:
* tooltips
* image lazy loaders
* drag and drop functionality

Actions can be added to an element with the `use` directive.

```html
<img use:lazyload data-src="giant-photo.jpg>
```

Data may be passed to the action as an object literal (e.g. `use:b="{ setting: true }"`, a literal value (e.g. `use:b="'a string'"`), or a value or function from your component's state (e.g. `add:b="foo"` or `add:b="foo()"`).

Actions are defined in a "actions" property on your component definition.

```html
<script>
  export default {
    actions: {
      b(node, data) {
        // do something
        return {
          update(data) {},
          destroy() {}
        }
      }
    }
  }
</script>
```

A action is a function which receives a reference to an element and optionally the data if it is added in the HTML. This function can then attach listeners or alter the element as needed. The action can optionally return an object with the methods `update(data)` and `destroy()`.

When data is added in the HTML and comes from state, the action's `update(data)` will be called if defined whenever the state is changed.

When the element is removed from the DOM `destroy()` will be called if provided, allowing for cleanup of event listeners, etc.

See #469 for discussion around this feature and more examples of how it could be used.
  • Loading branch information
jacwright committed Mar 19, 2018
1 parent bc416a5 commit 04f5d5c
Show file tree
Hide file tree
Showing 33 changed files with 1,025 additions and 132 deletions.
20 changes: 19 additions & 1 deletion src/generators/Generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export default class Generator {
components: Set<string>;
events: Set<string>;
transitions: Set<string>;
actions: Set<string>;
importedComponents: Map<string, string>;
namespace: string;
hasComponents: boolean;
Expand Down Expand Up @@ -134,6 +135,7 @@ export default class Generator {
this.components = new Set();
this.events = new Set();
this.transitions = new Set();
this.actions = new Set();
this.importedComponents = new Map();
this.slots = new Set();

Expand Down Expand Up @@ -452,7 +454,7 @@ export default class Generator {
templateProperties[getName(prop.key)] = prop;
});

['helpers', 'events', 'components', 'transitions'].forEach(key => {
['helpers', 'events', 'components', 'transitions', 'actions'].forEach(key => {
if (templateProperties[key]) {
templateProperties[key].value.properties.forEach((prop: Node) => {
this[key].add(getName(prop.key));
Expand Down Expand Up @@ -636,6 +638,12 @@ export default class Generator {
addDeclaration(getName(property.key), property.value, 'transitions');
});
}

if (templateProperties.actions) {
templateProperties.actions.value.properties.forEach((property: Node) => {
addDeclaration(getName(property.key), property.value, 'actions');
});
}
}

if (indentationLevel) {
Expand Down Expand Up @@ -824,6 +832,16 @@ export default class Generator {
this.skip();
}

if (node.type === 'Action' && node.expression) {
node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
if (node.expression.type === 'CallExpression') {
node.expression.arguments.forEach((arg: Node) => {
arg.metadata = contextualise(arg, contextDependencies, indexes, true);
});
}
this.skip();
}

if (node.type === 'Component' && node.name === ':Component') {
node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
}
Expand Down
7 changes: 7 additions & 0 deletions src/generators/nodes/Action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Node from './shared/Node';

export default class Action extends Node {
name: string;
value: Node[]
expression: Node
}
Loading

0 comments on commit 04f5d5c

Please sign in to comment.