or "Things are going to break"
We left our application over the weekend, secure in the knowledge that it was returning data from our primary persistent class, User.Widget. However, Widgets Direct are the premier supplier of both Widgets AND Widget Accessories, so we should really start working on adding these Accessories to our application.
We should do some housekeeping first though. Our Page Controlller code is currently sitting in the widgetmaster.js file. As we start to build up our application and use multiple controllers, this will make the PageController hard to find, so we should refactor it into a sensible location and file name. So let's create modules/page/PageController.js under our web application, and paste the code in there. We can then remove the controller code from widgetmaster.js
Let's save and reload our application to make sure everything works
Well, this clearly isn't good. How can we find out what went wrong though? As this is all client side code, we're not going to find any errors on the server. Instead, we need to press F12 to open our browser's debugger (these examples use Chrome, which is my personal preference as far as debuggers go, but all the major browsers have an equivilant). All errors in the runtime will log to the Console, so find this in your debugger. You may need to reload the page to trigger the error again.
The Angular framework very helpfully includes a link to the documentation to unpack any errors returned. This error is telling us that it can not find the function definition of PageController in the Angular runtime. We just refactored it into a new file, so why can't Angular see it? Did we add the new script to the CSP page, so that Angular was able to access it?
So we have learned a new lesson. The parent page must reference all scripts containing content we are trying to use. Once we add the new pagecontroller.js as a reference, we can reload our page successfully.
Onto the accessories. Accessory information is held in the User.WidgetAccessory class, and this is linked to the User.Widget class as a many to many relationship, through the use of a bridge class (please refer to the Many to Many section of the Caché documentation for more info, I'm not going to cover this in depth here). Our accessory class has a number of properties, and our bridge class has just 2, one link to Widget, and one link to Accessory, each with an Inverse property.
To start with, we would like to output all compatible accessories with our Widgets, so we need to add these as part of our toJSON() method, as an array. We can do this very neatly, by iterating over the relationship using GetNext to return all Accessory objects, and return the toJSON output from each. We can then push this output onto a JSON array, and attach this to a property of the Widget JSON.
Let's compile this, and reload our page to check that everything is still rendering OK.
Well, this clearly isn't good. That's the error message we put in to trap any failures from the REST Service. This means we have an error on the server. However, we should still start with our trusty friend, the F12 debugger. This will display the error as it was returned to the client. This may not seem any more useful than loading the service using a REST debugger, but when the setup becomes more complex (with Authentication, for example), it can be very useful to trap the exact failure scenario that the client recorded. So, we load up the debugger, and check the console.
We have an error on the GET. In the Chrome debugger we can actually click this link to take us to the Timeline view, which will show all server calls, and highlight the failed calls in red. We can then click this link to get the error message returned from the server.
Clicking on the red link gives us
So, it looks like we got a bit excited earlier and referenced our Access ory class before we defined a toJSON method for it. Let's go and define a basic one now (you may notice something missing from this, it's on purpose and will be covered next time)
So, we can now compile our Accessory class and reload our page. Hopefully everything should now be returning correctly from the REST service and the page should display
We have a working page again, but we're not displaying anything about Accessories. Let's check our JSON output has some information about these accesssories
We have our linked accessories populating arrays for each widget. As this has been a pretty long lesson so far, let's just do something simple and display a count of compatible accessories for each widget. We will add this to the header of each card, and just return the length of each array to serve as our count, and we can start doing more interesting things with them next time. As in our last lesson, we don't need to do anything special to start using these new data element, we just need to reference them.
After a quick compile, we now have our Accessories linking to our Widgets
In this lesson we:
- Broke our application by not referencing our controller JS
- Fixed our application by using our browser debugger
- Implemented a new Accessory class, and a relationship class to connect it to our Widget class
- Broke our application by failing to add a toJSON to our new class
- Fixed our application by using our browser debugger to identify the issue
In our next lesson we will:
- Expand our data model by completing our Accessory toJSON
This article is part of a multi-part series on using Angular on top of Caché REST services. The listing of the full series can be found at the Start Here page