What is the best way to replace HttpClient in Aurelia?

I am completely new to Aurelia.

How can I modify the code below in order to implement a dummy HttpClient, such as a json reader, that will provide a static set of json data without the need for a server during development?

import {inject} from 'aurelia-framework';
import {HttpClient} from 'aurelia-fetch-client';

@inject(HttpClient)
export class Users {
  heading = 'Sample Users';
  users = [];

  constructor(http) {
    http.configure(config => {
      config
        .useStandardConfiguration()
        .withBaseUrl('https://api.github.com/');
    });

    this.http = http;
  }

  activate() {
    // Instead of fetching real data from 'users', we can change it to fetch static JSON data here
    return Promise.resolve([{ name: 'John Doe', age: 30 }, { name: 'Jane Smith', age: 25 }])
      .then(users => this.users = users);
  }
}

Answer №1

To adapt the demo code in your initial post for substituting HttpClient implementations, there are a few steps to follow.

Step 1

Firstly, remove the configuration code from the class constructor...

The lines to be removed from users.js:

...
http.configure(config => {
  config
    .useStandardConfiguration()
    .withBaseUrl('https://api.github.com/');
});
...

These lines should be relocated to the main.js file:

main.js

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging();

  configureContainer(aurelia.container); 

  aurelia.start().then(a => a.setRoot());
}

function configureContainer(container) {
  let http = new HttpClient();
  http.configure(config => {
    config
      .useStandardConfiguration()
      .withBaseUrl('https://api.github.com/');
  });
  container.registerInstance(HttpClient, http);
}

Once this adjustment is made, the contents of users.js should appear as follows:

users.js

import {inject} from 'aurelia-framework';
import {HttpClient} from 'aurelia-fetch-client';

@inject(HttpClient)
export class Users {
  heading = 'Github Users';
  users = [];

  constructor(http) {
    this.http = http;
  }

  activate() {
    return this.http.fetch('users')
      .then(response => response.json())
      .then(users => this.users = users);
  }
}

Step 2:

Create a mock for the HttpClient.

The user.js module relies solely on the fetch method which returns a Response object featuring a json method. Below is a basic mock setup:

let mockUsers = [...todo: create mock user data...];

let httpMock = {
  fetch: url => Promise.resolve({
    json: () => mockUsers
  })
};

Step 3:

Adjust the container to utilize the http mock:

In step 1, we introduced a configureContainer function within the main.js module that registered a configured HttpClient instance into the container. To switch to our mock version, modify the configureContainer function as illustrated below:

main.js

...

let mockUsers = [...todo: create mock user data...];

let httpMock = {
  fetch: url => Promise.resolve({
    json: () => mockUsers
  })
};

function configureContainer(container) {      
  container.registerInstance(HttpClient, httpMock);
}

Further information on configuring the container can be found here: https://github.com/aurelia/dependency-injection/issues/73

Answer №2

An alternative approach to providing static data for application development is by utilizing Navigation Skeleton with Gulp and BrowserSync to simulate API calls.

For example, if you are loading JSON data from a virtual directory like /api, you can fake the API call:

GET /api/products

To achieve this, you only need to do two things:

Store mock data in files

Create an /api folder in the root directory of your Aurelia app.

In the /api/products subfolder, create a new file named GET.json containing the desired JSON structure, such as:

GET.json

[ { "id": 1, "name": "Keyboard", "price": "60$" },
  { "id": 2, "name": "Mouse", "price": "20$" },
  { "id": 3, "name": "Headphones", "price": "80$" }
]

Configure BrowserSync to simulate API calls

Edit the serve.js file located in the /build/tasks folder. Update the serve task definition with the following code:

gulp.task('serve', ['build'], function(done) {
  browserSync({
    online: false,
    open: false,
    port: 9000,
    server: {
      baseDir: ['.'],
      middleware: function(req, res, next) {
        res.setHeader('Access-Control-Allow-Origin', '*');

        // Simulate API calls
        if (req.url.indexOf('/api/') > -1) {
          console.log('[serve] responding ' + req.method + ' ' + req.originalUrl);

          var jsonResponseUri = req._parsedUrl.pathname + '/' + req.method + '.json';

          var jsonResponse = require('../..' + jsonResponseUri);

          req.url = jsonResponseUri;
          req.method = 'GET';
        }

        next();
      }
    }
  }, done);
});

Upon running gulp serve, BrowserSync will emulate the API calls by serving data from static files on disk.

For a practical example, visit my GitHub repository. More insights can be found in my article on Mocking API calls in Aurelia.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Enhance the speed of my Tumblr page by using JavaScript for personalized styling tweaks

-- Hey there! Dear Reader, if navigating Tumblr isn't your cup of tea, let me know and I'll provide more detailed instructions! I recently ran into some glitches on my Tumblr page while using the default theme 'Optica'. Whenever I tri ...

Failing to include a valid string in the path will result in an

Within my node API, I have a function that updates the email address array for either a contact or a farm. The concept is the same, but the difference lies in where the array is located: in farms it's within Records.emails, and in Contacts it's s ...

Ways to enlarge the parent container and reveal a concealed child element upon hovering without impacting neighboring containers

Currently, I am diligently working on the company service boxes and have a particular need... When hovering over: 1. The parent div should scale up and acquire box shadow without impacting the neighboring service boxes (it should appear to stand out above ...

Repeated tweets detected within real-time Twitter stream

I've been working on developing a live update Twitter feature, but I've noticed that it sometimes duplicates tweets and behaves erratically. Did I make a mistake somewhere in my code? http://jsfiddle.net/JmZCE/1/ Thank you in advance (note: I p ...

"Encountering a problem with a function showing an undefined error

Trying to incorporate a slider feature into my application led me to reference this w3schools sample. However, upon loading the page, the images briefly appear before disappearing. Additionally, clicking on the arrow or dots triggers an error stating: U ...

When converting to .glb format, the material becomes invisible unlike in .gltf files

After exporting a model using the glTF exporter in Blender 2.8, I noticed that when exporting to .glb format, the texture is no longer visible. Strangely, when I view the .glb file in the glTF Viewer from it appears fine, but in my environment and in the ...

Having trouble with importing files from a different folder in a React Typescript project

I have a specific folder arrangement set up https://i.sstatic.net/GFOYv.png My goal is to bring both MessageList.tsx and MessageSent.tsx into my Chat.tsx file // Chat.tsx import React from 'react' import {MessageList, MessageSent} from "./ ...

Looking for nested objects within an array in JavaScript

Currently, I am dealing with a REST API that provides data in the following format: students = [{ batch_id: 22 id: 1 image: null name: "a new batch student", attendance: [ { id: 1, student_id: 1, batch_id: 22, absent_on: "2019-09-15", ti ...

Comparing SHA and Python hashlib outputs show discrepancies with identical inputs

These code snippets both use Nodejs and Python to calculate a hash from the same input content, however they seem to be generating different results which is quite puzzling. // npm install jssha const jssha = require("jssha"); var s = new jssha(& ...

Having an issue with button onClick functionality not working in Javascript

Simple enough. I am struggling to get my button to generate the necessary input upon clicking. The fields should populate where the "household" class is located. I am limited to editing only Javascript and not HTML. Any suggestions? HTML: <ol ...

Apply a class to each element that contains the specified name attribute

I have successfully implemented a prices tab on the top of my page, with tabs for different packages at the bottom. When a user selects a certain package, only specific items from the list are visible while the others are hidden. I managed to streamline ...

The $http function would refresh and store new data in localStorage on a weekly

If we use $http in Angular to fetch data for a week, and the data remains unchanged throughout the week. However, every Sunday the data gets updated using $http.get. My question is, when new data is fetched, will it also update the data stored in local sto ...

Are the elements in the second array the result of squaring each element in the first array? (CODEWARS)

I am currently working on a 6kyu challenge on codewars and I've encountered a frustrating issue that I can't seem to figure out. The task at hand involves comparing two arrays, a and b, to determine if they have the same elements with the same mu ...

Is it possible to implement a single lightbox modal that can display multiple images?

I am looking to create a fullscreen lightbox modal for multiple images, but I have been facing issues with finding the right solution. Most lightbox modals out there rely on jQuery and older versions of Bootstrap. Here is what I have tried so far: HTML: ...

What is the most effective method for incorporating personalized React components in the midst of strings or paragraph tags

Summary: Exploring the frontend world for the first time. Attempting to integrate custom components within p-tags for a website, but facing challenges in making them dynamically changeable based on user interaction. Greetings all! As a newbie in front-end ...

Launching the node application using `node` as the starting command is successful, however, using `/usr/bin/node` as the starting

My goal is to configure a node application as a service. To start the service, I must initiate node with an absolute path, specifically using usr/bin/node. However, my application seems to malfunction when launched with this absolute path for unknown rea ...

Get the Vue.js package from Node.js by downloading the zip file

I am having trouble downloading a zip file from nodejs using vuejs. The issue I am facing is that an odd underscore appears around the fileName when the dialog box pops up. If I manually set the fileName like this: const fileName = "xmlFile.zip"; Then t ...

Issue with resetting the state of a react-select component remains unresolved

I'm currently facing two issues with my react-select component: Firstly, once I select an option, I am unable to change it afterwards. Second, when my form is reset, the react-select component does not reset along with the other fields. For simplici ...

Obtain a string in JSON format upon clicking in Angular 2

I am working on extracting the title from a json response using a click event. Currently, I can retrieve all the titles when the button is clicked, but I am looking for a way to obtain a specific title based on the button or a href that the user has clicke ...