Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Designer Readme: some tweaks and add info about exporting. #171

Merged
merged 1 commit into from
Oct 13, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 28 additions & 23 deletions js/designer_components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,26 @@

## Intro

So you want to make a Designer Component that updates dynamically in the Desginer?
So you want to make a Designer Component that updates dynamically in the Designer?
First - this relies on Javascript.
It also plays around with Skulpt.
It's not officially supported.
It may need updating in the future since it relies on some hackery and implementation details that may change in the future.

BUT it is isolated to the Desiner so if does stop working - the actual python won't be affected.
BUT it is isolated to the Designer, so if it does stop working - the actual Python code won't be affected.

### Notes
Your custom component must be an HTMLPanel.
We essentially create a Javascript version of our CustomComponent.
Anvil never calls the Python class in the Designer so that's why we need to inject our own Javascript version.
In the Python code we remove the script tags in the `__init__` method so that the Javascript version is never injected.

Anvil never calls the Python class in the Designer, so that's why we need to inject our Javascript version.
In the Python code, we remove the script tags in the `__init__` method. This way we do not inject the Javascript version into Python.

## Where to start?

Write the python version first!
Write the Python version first!

When you want to create a Designer version look at the comments in `DesignerComponent.ts`.
Anything that is marked as `private` should NOT be overriden.
When you want to create a Designer version, first look at the comments in `DesignerComponent.ts`.
Anything marked as `private` should NOT be overridden.

- Does your Python class have injected `css`?
- *override the `static css` property*
Expand All @@ -37,7 +36,7 @@ Anything that is marked as `private` should NOT be overriden.

You must override the `init()` method and then call `super.init()`

The custom component html must have a domNode with an identifiable selector.
The custom component HTML must have a domNode with an identifiable selector.
e.g.

```html
Expand All @@ -51,9 +50,9 @@ The first argument to `super.init()` should be the selector to identify your cus
}
```

An optional second argument can be used. Which is a className. This className will be added to the HTMLPanel dom node.
In the Designer world its purpose is to be a flag to prevent instantiating the same domNode multiple times.
But it can be used to add classes to the HTMLPanel you would otherwise have added in your python init method.
An optional second argument can be used, which is a className. This className will be added to the HTMLPanel's domNode.
In the Designer world, its purpose is to be a flag to prevent instantiating the same domNode multiple times.
The second argument can be used to add a class to the HTMLPanel you would otherwise have added in your Python `__init__` method.

```typescript
static init() {
Expand All @@ -69,22 +68,28 @@ After the `init` method is called we call the constructor.
There is no need to override the `constructor()` method - but you may want to if you want to add attributes to your `this` argument.
The arguments to the `constructor()` will be:
- the HTMLPanel's domNode for your custom component.
- the python Component as a Skulpt object.
(A Skulpt object is what your client side Python object looks like in Javacsript)
- the Python Component as a Skulpt object.
(A Skulpt object is what your client-side Python object looks like in Javascript)
- the domNode of the element found from the querySelector used in the `init()` method


### `setProp(propName, propVal, props)`
### `setProp(propName, propVal, props)`, `update(props, propName, propVal)`

You will need to override `setProp` or `update` (but not both).

You will need to override `setProp` or `update` (but not both). It's probably better to override `setProp`.
(`update` was used in the initial versions and `setProp` was later added as a better implementation).
In `setProp` you get the `propName` and the `propVal` as well as all the current `props`.
In `setProp` you get the `propName` and the `propVal`, as well as all the current `props`.
These are the raw Javascript values.
You can either update the dom directly or work with the Skulpt Python objects.
There are some helper methods for common properties like `visible` and working with `color`.

The DesignerChips component is an example that uses `setProp` and works with both Skulpt objects and the dom to update itself when a property changes.
The `DesignerChips` component is an example that uses `setProp` and works with both Skulpt objects and the dom to update itself when a property changes.

`update` is typically in place of `setProp` when you update your entire component whenever a property changes.
The advantage of `update` is that it is only called once on the first load, whereas `setProp` is called once per prop on the first load.


## Exporting your Designer class
- To make your class available you need to export it in `js/designer_components/index.ts`
Comment on lines +91 to +92
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to add this point


## Bundling the javascript
- Install deno
Expand All @@ -96,7 +101,7 @@ The DesignerChips component is an example that uses `setProp` and works with bot

## Hacking

In each designer component you'll see code like
In each designer component, you'll see code like

```html
<script type="module">
Expand All @@ -108,11 +113,11 @@ In each designer component you'll see code like
</script>
```

You'll need equivalent code in your custom component's html.
You'll need equivalent code in your custom component's HTML.

When hacking, there's no need to worry about the deno link. Instead:
- bundle the Javascript (see above instructions)
- Copy the bundled file into your theme assets.
- Replace the deno url with a relative theme url: `_/theme/bundle.js`
- Replace the deno URL with a relative theme URL: `./_/theme/bundle.js`

Whenever you change the local files re-bundle and repeat.
Whenever you change the local files, re-bundle and repeat.