Creating¶
The next step is to add the code to create new modules. Create a new file src/js/routes/modules/new.jsx
and add the following code:
import m from "mithril";
import Athena from "../../athena.jsx";
import api from "../../api.js";
export default function New() {
let code = "";
let name = "";
let semester = "WS18/19";
function setCode(ev) {
code = ev.target.value;
}
function setName(ev) {
name = ev.target.value;
}
function setSemester(ev) {
semester = ev.target.value;
}
function createModule(ev) {
ev.preventDefault();
m.request({
method: "POST",
url: `${api.base}/modules`,
body: {
data: {
type: "modules",
attributes: {
code,
name,
semester,
},
relationships: {
teacher: {
data: {
type: "users",
id: 1,
},
},
},
},
},
}).then((data) => {
m.route.set("/modules");
});
}
/**
* render the component
*/
return {
view: (vnode) => {
return (
<Athena>
<main className="row justify-content-center">
<div className="col-lg-6">
<h1>Create new Module</h1>
<form onsubmit={(ev) => createModule(ev)}>
<div className="form-group">
<label>
Code
<input type="text" className="form-control" onchange={(ev) => setCode(ev)}
/>
</label>
<label>
Name
<input type="text" className="form-control" onchange={(ev) => setName(ev)}
/>
</label>
<label>
Semester
<select onchange={(ev) => setSemester(ev)}>
<option value="WS18/19">Wintersemester 18/19</option>
<option value="SS18">Summersemester 18</option>
</select>
</label>
<div className="btn-container">
<m.route.Link href={"/modules"} className="btn btn-secondary">
Don't Create
</m.route.Link>
<button type="submit" role="button">
Create
</button>
</div>
</div>
</form>
</div>
</main>
</Athena>
);
},
};
}
As you can see there are no major differences between the React version and the Mithril version. As in the index.jsx
, we see that state is defined directly on the object and not via an intermediate state object. Similarly, this can then be accessed via the property, without the detour of the state
.
The one bigger difference is in the createModule
function, where we have to explicitly specify the request to be sent to create our new module. The core data part is similar to the React version, but here we need to explicitly set the URL and also the request method. In the JSONAPI specification, to create a new object, we use the same URL as to get the collection of objects, but we use the 'POST'
request type, to indicating that we are posting new data to the server. The other difference here is that because routing is included in Mithril, we can use mithril.route.set('/modules')
to explicitly navigate to the list of modules, without having to go via setting a creation flag.
If you take a closer look to the body
we provide, you can see that we pass the variables directly. This is a shorthand form available in ES6 if the attribute and the variable are named alike, e.g code
is short for code: this.code
.
To make it work, we need to link it in to our application. First include it into the src/js/index.js
route definitions:
import m from 'mithril';
import Athena from './athena.jsx';
import ModulesIndex from './routes/modules/index.jsx';
import New from './routes/modules/new.jsx';
const root = document.getElementById('app-entry-point')
m.route(root, '/', {
'/': Athena,
'/modules': ModulesIndex,
'/modules/new': New
});
Then update the src/js/routes/modules/index.jsx
to link to the new route, adding the href
and oncreate
attribtes:
...
<li><m.route.Link href={'/modules/new'} role="menuitem" tabindex="-1">Create Module</m.route.Link></li>
...
Now you should be able to navigate to the new route and create a new module.