atomicreact
Version:
AtomicReact is a framework to build web apps with atomicity concept
435 lines (327 loc) • 12.2 kB
Markdown
# Atom
The minimal particle is called by **Atom**. One Atom is composed by 3 parts:
* [**Structure (HTML)**](Atom?id=structure-html)
* [**Logic (JS)**](Atom?id=logic-js)
* [**Style (CSS)**](Atom?id=style-css)
Fundamentally, an Atom **need to have a structure but doesn't need a logic and style**.
After runnning [`Atomic` command](AtomicCLI?id=atomic), your `AtomicDir` is created and there will be your Atoms.
In the `AtomicDir` there are three directories: *html, js, css*.
``` text
└── AtomicDir
├── html
├── js
└── css
```
The `html`subfolder is the **Atom's structure**.
The `js` subfolder is the **Atom's logic**.
The `css` subfolder is the **Atom's style**.
**In order to generate an Atom** just create an *.html* file in the `html` subfolder. **The name of the file is the Atom name or the Atom key**. Note that if you change the `debug` to *true* in the `AtomicReact_config.js` file then you should see the Atom loaded on console.
Let's suppose you have created a file called `MyFirstAtom.html` in the `html` subfolder. Therefore the Atom Key is: *`MyFirstAtom`*.
## Structure (HTML)
``` text
└── AtomicDir
├── html <<<---
├── js
└── css
```
Inside `AtomicDir/html` there will be Atom's structure. Each Atom has its own file structure with an `.html` extension. **The name of the file is the Atom name or the Atom key**, so if you create a file called `MyFirstAtom.html` inside `AtomicDir/html` then your **Atom key** is `MyFirstAtom`.
Atom's struture is any *html* struture, but it is recommended that each structure stays within a **single tag**. For exemple:
In `MyFirstAtom.html` file:
**Recommended:**
```html
<div>
<!-- All Atom's structure will be here -->
</div>
```
**Not recommended (but possible):**
```html
<div>Foo</div>
<div>Bar</div>
```
### Overview
* [`nucleus`](Atom?id=nucleus)
* [`props`](Atom?id=props)
* [`sub`](Atom?id=sub)
### Nucleus
**`nucleus`** is the place where all Atom's children are located.
**In order to set** the Atom's `nucleus`, just type `atomic.nucleus` inside Atom's struture.
```html
<AnyTag atomic.nucleus></AnyTag>
<!-- Note: AnyTag maybe a Html Tag or a Atom Key also -->
```
**To add** something in *nucleus*, just insert it inside Atom's tagging. See below:
```html
<MyFirstAtom>
<!-- All here will be on Nucleus even this comment -->
<h2>Hey! I'll be inside Atom's Nucleus !</h2>
</MyFirstAtom>
```
You can also add an Atom programatically with [`add()`](Atom?id=add) function.
#### Exemple:
In `MyFirstAtom.html`:
```html
<div>
<h1>This is MyFirstAtom</h1>
<ul atomic.nucleus></ul> <!-- Set this ul as nucleus -->
</div>
```
In `index.html`:
```html
<MyFirstAtom>
<li>Foo</li>
<li>Bar</li>
<li>The life is good</li>
</MyFirstAtom>
```
You can see this example on [Playground](https://playground-atomicreact.herokuapp.com/1ve7ZgLSM8rsN8ZPDgKM-25F-YQn8nbQ7)
### Props
`props` are the Atom's properties. They're used to set Atom's initial state.
**To use** `props`, just type `props.anyPropKey` **between pairs of braces** anywhere in the *Atom's Structure*, as follows:
```html
{props.<anyPropKey>}
```
**To assign** `props` a value, just type `props.anyPropKey="someValue"` inside Atom's tagging, see below:
```html
<MyFirstAtom props.anyPropKey="someValue"></MyFirstAtom>
```
#### Exemple:
In `MyFirstAtom.html`:
```html
<div style="border: 1px solid {props.borderColor};">
<h2>{props.theTitle}</h2>
</div>
```
In `index.html`:
```html
<MyFirstAtom props.theTitle="This is my Title" props.borderColor="#FF0000"></MyFirstAtom>
```
You can see this example on [Playground](https://playground-atomicreact.herokuapp.com/1K16qhgvUc-IVJVMDiWisjO9tBPf7Lxyw)
### Sub
An Atom may have *important elements* which we can handle them, they're called **`sub` particles**. The `atomic.sub` is used for setting any element inside an Atom as its *sub part* and easily to get it with [`getSub()`](Atom?id=getsub) function. An Atom can have none, one or many `sub`.
**To set** any element as `sub`, just type `atomic.sub="anySubName"` inside the elements tagging.
```html
<AnyTag atomic.sub="anySubName"></AnyTag>
<!-- Note: AnyTag may be a Html Tag or a Atom Key also -->
```
#### Exemple:
In `MyFirstAtom.html`:
```html
<div>
<button atomic.sub="btnShowAlert">Show Message!</button>
</div>
```
In `MyFirstAtom.js`:
```js
class MyMain {
onRender() {
var btnShowAlert = this.getSub('btnShowAlert'); //get button element DOM
btnShowAlert.onclick = function(e){ //button's onclick event
alert("the button was clicked"); // alert a message
}
}
}
module.exports.main = MyMain;
```
In `index.html`:
```html
<MyFirstAtom></MyFirstAtom>
```
You can see this example on [Playground](https://playground-atomicreact.herokuapp.com/1oijsksTIpt0CjajAgpXPJA2FfV89OFqT)
## Logic (JS)
``` text
└── AtomicDir
├── html
├── js <<<---
└── css
```
Inside `AtomicDir/js` there is Atom's whole logic. Each Atom has its own logic, so if you create an Atom called by `MyFirstAtom.html` on `AtomicDir/html`, its respective logic will be in `AtomicDir/js/MyFirstAtom.js`.
### Main Class
All Atom's logic code will be **inside the main class** and you can export it with `module.exports.main` like:
```js
class MyMain {
/* [...] */
}
module.exports.main = MyMain; //export MyMain Class as main
```
So we can use reserved functions or create custom functions inside the main class, like this:
```js
class MyMain {
onRender() {
/* Does something when this atom is rendered */
console.log('atom: ', this.getElement());
console.log("atom's nucleus", this.getNucleus(atom));
this.myFunction();
}
onAdded(atomAdded) {
/* Does something when other atom is added inside this atom's nucleus */
console.log('atomAdded: ', atomAdded);
console.log('atom: ', this.getElement());
}
myFunction() {
/* myFunction is a custom function */
alert('Hey! this is myFunction !');
}
}
module.exports.main = MyMain; //export MyMain Class as main
```
You can see this example on [Playground](https://playground-atomicreact.herokuapp.com/1trq_CV833nF3vT6tjX1INshjhR4uPWHn)
**Note**:
* use `module.exports.main = <anyClass>` to export the main class (see last line in example above)
* four reserved functions were used in example above:[`getElement()`](Atom?id=getelement), [`getNucleus()`](Atom?id=getnucleus), [`onAdded`](Atom?id=onadded), [`onRender`](Atom?id=onrender).
The main class is exported to two places: [`Global Atomic Class`](AtomicClass) and to **Atomic object inside atom element**. See [Accessing Main Class](Atom?id=accessing-main-class) to know more.
#### Accessing Main Class
Sometimes we may want to access the main class from another Atom. We can do this accesing the `Atomic.main` class in an Atom element.
For example, let's suppose we have two Atoms (*myFirstAtom* and *mySecondAtom*) and the *myFirstAtom*'s logic is:
`myFirstAtom.js`
```js
class MyFirstAtomMain {
onRender() {}
myFunction() {
alert('Hey! this is myFunction !');
}
}
module.exports.main = MyFirstAtomMain;
```
And then we want to call **myFunction()** in *myFirstAtom*'s main class from *mySecondAtom*. So the *mySecondAtom*'s logic will be:
`mySecondAtom.js`
```js
class MySecondAtomMain {
onRender() {
var myFirstAtom = this.getSub('myFirstAtomSub'); //see the note¹
myFirstAtom.Atomic.main.myFunction();
// You can also access myFunction using Global Atomic Class:
Atomic.getAtom('myFirstAtom').main.myFunction(); //see note²
}
}
module.exports.main = MySecondAtomMain;
```
You can see this example on [Playground](https://playground-atomicreact.herokuapp.com/1hFkTzjJt82ZU9oAu12Ikzhxgxa4-AFT9)
**Note**:
* [1] - In example above *myFirstAtom* is a [sub part](Atom?id=sub) of *mySecondAtom*:
`mySecondAtom.html`
```html
<div>
<myFirstAtom atomic.sub="myFirstAtomSub"></myFirstAtom>
</div>
```
* [2] - Checkout [`Atomic.getAtom()`](AtomicClass?id=getatom)
---
The main class **exported to Atom element** has some reserved functions. See below:
### Overview
* [`add()`](Atom?id=add)
* [`getElement()`](Atom?id=getelement)
* [`getNucleus()`](Atom?id=getnucleus)
* [`getSub()`](Atom?id=getsub)
* [`onAdded`](Atom?id=onadded)
* [`onRender`](Atom?id=onrender)
### add()
``` js
add(AtomKey, props, where)
```
* **Description:**
Add an Atom inside an Atom's [**Nucleus**](Atom?id=nucleus).
* **Param:**
Param | Description | Type | Default value
------------ | ------------- | ------------- | -------------
AtomKey | key of Atom will be added | `string` |
props | Atom's [`Prop`](AtomicClass?id=prop) array | `Prop Array` | [ ]
where | Representing the position relative to the element's nucleus tag. Must be: `beforebegin`, `afterbegin`, `beforeend` or `afterend`. [Checkout this](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML#Parameters) to know more. | `string` | *beforeend*
##### Prop:
A key pair object containing the prop's key declared in [Atom's Structure](Atom?id=props) and its value. As follows:
``` js
{
key: "myTitle",
value: "This is my title"
}
```
Where:
`key`'s value is a `string`
`value`'s value is a `string`
* **Return:** atom element added as `DOM Element`
---
### getElement()
``` js
getElement()
```
* **Description:**
Get the Atom's [*element*](https://www.w3schools.com/jsref/dom_obj_all.asp)
* **Param:** void
* **Return:** the element as `DOM Element`
---
### getSub()
``` js
getSub(subName)
```
* **Description:**
Get an Atom's [*sub element*](Atom?id=sub) by its name.
* **Param:**
Param | Description | Type
------------ | ------------- | -------------
subName | Sub's name declarated in [Atom Structure - Sub](Atom?id=sub) | `string`
* **Return:** the sub element as `DOM Element`
---
### getNucleus()
``` js
getNucleus()
```
* **Description:**
Get the Atom's [*Nucleus element*](Atom?id=nucleus)
* **Param:** void
* **Return:** the nucleus element as `DOM Element`
---
### onAdded()
``` js
onAdded(atomAdded)
```
* **Description:**
this function is fired when another Atom is added inside the Atom.
* **Param:**
Param | Description | Type
------------ | ------------- | -------------
atomAdded | Atom which was added | `DOM Element`
---
### onRender()
``` js
onRender()
```
* **Description:**
this function is fired when an Atom is rendered.
* **Param:** void
---
## Style (CSS)
``` text
└── AtomicDir
├── html
├── js
└── css <<<---
```
Inside `AtomicDir/css` will be all of Atom's style. It's recommended that each Atom's style stay within a single file. When AtomicReact bundle the styles, it just joins all css files into one.
In order to style an Atom we just **code a normal CSS with selectors** using `data-atomic-key`, `data-atomic-nucleus` and `data-atomic-sub` attributes. See the example below:
**To consider the examples below, suppose the following `MyFirstAtom` Atom's Structure:**
```html
<div>
<h2 atomic.sub="myTitle">The Order List</h2>
<div atomic.nucleus></div>
</div>
```
### Styling the Atom
Let's suppose we want to style `MyFirstAtom` Atom with `border: 1px solid #F00`:
```css
[data-atomic-key="MyFirstAtom"] {
border: 1px solid #F00;
}
```
### Styling the Atom's Nucleus
Let's suppose we want to style the Atom's nucleus with `background-color: #00F`:
```css
[data-atomic-key="MyFirstAtom"] > [data-atomic-nucleus]{
background-color: #00F;
}
```
### Styling the Atom's Sub
Let's suppose we want to style the `myTitle` Atom's sub with `color: #0F0`:
```css
[data-atomic-key="MyFirstAtom"] > [data-atomic-sub="myTitle"]{
color: #0F0;
}
```