Now that you have your Router implemented and protected by authentication checks, it’s time to tack on the UI components to make it work end to end. The code for this is quite similar to the UI code you developed in Chapter 8, Creating a Beautiful User Experience. And remember that you can review the b4-final application in the downloads that accompany this book, which include all of the code as well.
Open your index.ts file for editing. You’ll need a couple of methods—the first of which is getBundles. Add this code toward the top of the file, right after fetchJSON:
| | const getBundles = async () => { |
| | const bundles = await fetchJSON('/api/list-bundles'); |
| | if (bundles.error) { |
| | throw bundles.error; |
| | } |
| | return bundles; |
| | }; |
In the last chapter, the getBundles method called out to Elasticsearch directly over the proxy provided by webkit-dev-server. This time we’re using fetchJSON to hit the /list-bundles route that you added to bundle.js.
Next, create an addBundle async function after getBundles. You can start with the code from Saving Data with a Form, except that you should use fetchJSON rather than calling fetch directly.
After addBundle, insert the following listBundles function. This will be called to render the #list-bundles view.
| | const listBundles = bundles => { |
| | const mainElement = document.body.querySelector('.b4-main'); |
| | |
| | mainElement.innerHTML = |
| | templates.addBundleForm() + templates.listBundles({bundles}); |
| | |
| | const form = mainElement.querySelector('form'); |
| | form.addEventListener('submit', event => { |
| | event.preventDefault(); |
| | const name = form.querySelector('input').value; |
| | addBundle(name); |
| | }); |
| | }; |
And finally, you’ll need to add this #list-bundles case to the switch statement inside of the showView method.
| | case '#list-bundles': |
| | try { |
| | const bundles = await getBundles(); |
| | listBundles(bundles); |
| | } catch (err) { |
| | showAlert(err); |
| | window.location.hash = '#welcome'; |
| | } |
| | break; |
When rendering the #list-bundles view, first we grab the user’s book bundles using the getBundles method you just added. Then we send that collection to the listBundles method for rendering using the related templates.
If something went wrong (for example, if the session timed out), then the rejected Promise returned by getBundles will become a thrown exception. The catch clause ensures that we notify the user of the error and send him back to the welcome screen.
Save your index.ts if you haven’t already, and nodemon should acknowledge the changes. If you head back to http://b4.example.com:60900, everything should be in place to create and list book bundles associated with your account once you sign in.
Whew! That was a lot of work—but such is the nature of software development.
Filling in more of the behavior of the app will be left as an exercise for the reader. But before we close out this chapter, let’s talk about serving in production.