DADI Web's Built-in Data Helpers


  • DADI

    Over the last couple of years we've spent a lot of time debugging runtime issues with Events and the data they have access to.

    After a short introduction to Web's Event system, we cover two built-in helpers that are part of the data context for each page request in DADI Web.

    Events

    The Event system in DADI Web provides developers with a way to perform tasks related to the current request, end the current request or extend the data context that is passed to the rendering engine.

    An Event is a JavaScript file stored in your application's workspace folder and attached to a page.json file using the "events" array:

    "events": [
      "my-event"
    ]
    

    It is declared in the following way, receiving the original HTTP request, the response, the data context and a callback function to return control back to the controller that called it:

    const Event = function (req, res, data, callback) {
    
    }
    

    The data context

    The data argument that an Event receives is JSON which is eventually passed to the template rendering engine once all the Datasources and Events have finished running. data may contain some or all of the following:

    • metadata about the current page
    • request parameters
    • data loaded by all datasources that have been run before the Events started executing
    • data added by previous Events
    • global configuration settings
    {
      "query": {},
      "params": {
        "category": "beauty",
        "subCategory": "makeup"
      },
      "pathname": "/beauty-hair/makeup/article-one",
      "host": "127.0.0.1:8000",
      "debug": true,
      "page": {
        "name": "article", 
        "description": "Article page",
        "language": "en"
      },
      "global": {
        "baseUrl": "http://localhost:8000",
        "environment": "development"
      }
      "article": {
        "results": [
          {
            "slug": "article-one",
            "title": "Article One",
            "category": "beauty"
          } 
        ],
        "metadata": {
          "limit": 1,
          "page": 1,
          "totalCount": 19,
          "totalPages": 19,
          "nextPage": 2
        }
      }
    }
    

    Data from datasources

    All datasources that retrieve data from a DADI API return data in the following format:

    {
      "results": [
        {
          "slug": "article-one",
          "title": "Article One",
          "category": "beauty"
        } 
      ],
      "metadata": {
        "limit": 1,
        "page": 1,
        "totalCount": 19,
        "totalPages": 19,
        "nextPage": 2
      }
    }
    

    The results are added to the data context using the datasource's key property. Running a datasource configured with "key": "article" would result in the following in the data context:

    "article": {
      "results": [
        {
          ...
        } 
      ],
      "metadata": {
        ...
      }
    }
    

    Common Event errors

    While helping people to implement applications using DADI Web, we've encountered many issues when trying to access data within an Event that simply doesn't exist in the data context.

    No data loaded

    For example, making an assumption that the datasource "people" has returned results and the data context has been populated:

    let myPerson = data.people.results[0]
    

    If the context doesn't contain the "people" property, perhaps because the datasource wasn't attached to the page, then the Event fails with:

    TypeError: Cannot read property 'results' of undefined
    

    No "results" property

    Another way to cause an Event to fail is to reference an nonexistent "results" property. Perhaps the data we're expecting came from an API other than a DADI API (such as Twitter or Instagram) and the required data has a different structure.

    let mostRecentInstagramPhoto = data.instagram.results[0]
    

    If there isn't a "results" array at data.instagram, the Event will fail with:

    TypeError: Cannot read property '0' of undefined
    

    Introducing built-in helper functions

    With these two common errors in mind, we decided it was time to introduce some helper functions into the mix: has() and hasResults().

    These helpers are added to the data context before it is passed to the Event system:

    {
      has: [Function],
      hasResults: [Function],
      "query": {},
      "params": {
        "category": "beauty",
        "subCategory": "makeup"
      },
      ...
    }
    

    has()

    The has() function can be used to check that a property exists in the data context:

    const Event = function (req, res, data, callback) {
      if (data.has('instagram')) {
        // do something with data.instagram
      } else {
        // no instagram property
        res.statusCode = 404
        res.end('Not found')
      }
      
      callback()
    }
    

    hasResults()

    The hasResults() function can be used to check that the results of a DADI API datasource exist, and that there is at least one value in the "results" array:

    const Event = function (req, res, data, callback) {
      if (data.hasResults('people')) {
        // do something with people
        let mostRecentPerson = data.people.results[0]
      } else {
        // no people results
        res.statusCode = 404
        res.end('Not found')
      }
      
      callback()
    }
    

    Conclusion

    The two helper functions added to the data context in DADI Web help to make your application more robust and keep the code cleaner. Don't worry, we got tired of writing the same statements over and over as well:

    if (data.people &&
      data.people.results && 
      data.people.results[0]) {
      // finally do something
    }
    

    We hope you find these as useful as we have, and welcome any suggestions for additional helpers that might save you time and energy!

    For more information about Events in DADI Web, see the documentation.


  • DADI

    Could be cool to have a way to test a value in this way too. e.g.,

    data.isValue('people.results[0].name', 'Jim')
    

    Or maybe that's getting too far into the weeds?



  • @dave great idea!


Log in to reply
 

Looks like your connection to DADI Forum was lost, please wait while we try to reconnect.