# How to implement global storage?

**URL:** <https://discourse.aurelia.io/t/how-to-implement-global-storage/493>\
**Category:** Best Practices\
**Created:** [December 5, 2017, 3:03pm UTC](https://discourse.aurelia.io/t/how-to-implement-global-storage/493 "2017-12-05T15:03:25Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![iiiyx](https://avatars.discourse-cdn.com/v4/letter/i/54ee81/32.png) [@iiiyx](https://discourse.aurelia.io/u/iiiyx)\
**Post date:** [December 5, 2017, 3:03pm UTC](https://discourse.aurelia.io/t/how-to-implement-global-storage/493/1 "2017-12-05T15:03:25Z")

</div>

You have a Contact Manager tutorial. How can I implement a global storage for contacts to make it possible to get existing contact not from API, but from stored contact list?

---

<div class="post-metadata">

**Author:** ![winter\_limelight](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/winter_limelight/32/226_2.png) [@winter\_limelight](https://discourse.aurelia.io/u/winter_limelight)\
**Post date:** [December 5, 2017, 7:06pm UTC](https://discourse.aurelia.io/t/how-to-implement-global-storage/493/2 "2017-12-05T19:06:28Z")

</div>

I think this is what the tutorial does by default. The web-api.js that it gets you to [download](http://aurelia.io/downloads/contact-manager-assets.zip) stores the contacts in an array then returns them using a timeout and Promise to simulate an HTTP fetch. This is a snippet from that file:

```auto
let contacts = [...]
return new Promise(resolve => {
  setTimeout(() => {
	let results = contacts.map(x => ...);
	resolve(results);
  });
});
```

In practice, if you were caching, then this function would check to see if there was data in the cache (the cache being some local variable, or some other class injected using Aurelia’s DI) and if not make an HTTP fetch to get it. Something like this (typescript, and not tested):

```auto
export class Cache {
  public data:any = {};
  // in practice this would be more sophisticated - 
  // perhaps loading/saving from local storage, and exposing
  // its functionality via methods rather than a property
}

@autoinject
export class WebAPI {

  constructor(private httpClient: HttpClient, private cache: Cache) {}
  
  public getContactList(): Promise {
    const cacheKey = "contact-list";
    if(this.cache[cacheKey])
      return new Promise(resolve => resolve(this.cache[cacheKey]));
    
    return this.httpClient.fetch("api/contractList")
      .then(response => response.json())
      .then(json => { 
        this.cache[cacheKey] = json;
        return new Promise(resolve => resolve(json));
      });
    });
  });
}
```

---

<div class="post-metadata">

**Author:** ![iiiyx](https://avatars.discourse-cdn.com/v4/letter/i/54ee81/32.png) [@iiiyx](https://discourse.aurelia.io/u/iiiyx)\
**Post date:** [December 6, 2017, 8:24am UTC](https://discourse.aurelia.io/t/how-to-implement-global-storage/493/3 "2017-12-06T08:24:38Z")

</div>

Thanks for the answer. I guess my question was not specified enough. Mostly my questions concerns global availability and bindability.  
I want to require Store from any component, take its Contacts with binding. So, if any other component changes the contacts then all other components will reactively update their view without any additional work (not a pub/sub approach).

I guess the right way is to implement noview-custom-element registred in global scope and then somehow bind to this component’s data from another components. Also this noview-custom-element should be singleton.

---

<div class="post-metadata">

**Author:** ![zewa666](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/zewa666/32/19_2.png) [@zewa666](https://discourse.aurelia.io/u/zewa666)\
**Post date:** [December 6, 2017, 4:30pm UTC](https://discourse.aurelia.io/t/how-to-implement-global-storage/493/4 "2017-12-06T16:30:49Z")

</div>

Im not fully sure I understand your requirements but take a look at this store approach [http://pragmatic-coder.net/using-a-state-container-with-aurelia/](http://pragmatic-coder.net/using-a-state-container-with-aurelia/)

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [December 6, 2017, 10:42pm UTC](https://discourse.aurelia.io/t/how-to-implement-global-storage/493/5 "2017-12-06T22:42:55Z")

</div>

It sounds like you don’t need any extra layer.

In your top level component, hold the contacts array model, then use two way binding to all child components.  
As long as you mutate the contacts using one of monitored array methods of Aurelia ArrayObserver, the mutation will automatically trigger UI updates on all components.

FYI, Aurelia ArrayObserver monitors following methods on array mutation: pop/push/reverse/shift/sort/splice/unshift.  
Assignment on the whole array also monitored, `contacts = newContacts;`.  
But `contacts[idx] = aNewContact;` doesn’t work.

Mutation within one of the contact should also work (propagate to all UI).

`app.js`

```auto
export class App {
  contacts = []; // need to populated when app boots up.
  /* ... */
}

```

`app.html`

```auto
<template>
  <child-comp1 contacts.two-way="contacts"></child-comp1>
  <child-comp2 contacts.two-way="contacts"></child-comp2>
<template>

```

Remember to use two way binding on `contacts` all way through nested child components.

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [December 6, 2017, 10:58pm UTC](https://discourse.aurelia.io/t/how-to-implement-global-storage/493/6 "2017-12-06T22:58:17Z")

</div>

My above solution doesn’t work if using routing, which dynamically composes child component.

You are right, you need an object to hold the contacts model and related logic, but it doesn’t need to be a UI component.

Just build a class to hold contacts model, then use dependency injection on all your components. The default behavior of aurelia dependency injection is to use singleton instance on all injections which is exactly what you want.

`contacts-service.js`

```auto
@inject(HttpClient)
export class ContactsService {
  contacts = []; // to be populated using fetch api.

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

  getContact(id) { /* get a local copy of contact */}
  /*...*/
}

```

`some-component-to-display-one-contact.js`

```auto
@inject(ContactsService)
export class SomeComponentToDisplayOneContact {
  contact = null;

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

  activate(params, routeConfig) {
    this.contactId = params.contactId; // assume you have contactId on the route
    this.contact = this.contactsService.getContact(this.contactId);
  }
}

```

---

<div class="post-metadata">

**Author:** ![winter\_limelight](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/winter_limelight/32/226_2.png) [@winter\_limelight](https://discourse.aurelia.io/u/winter_limelight)\
**Post date:** [December 7, 2017, 12:14am UTC](https://discourse.aurelia.io/t/how-to-implement-global-storage/493/7 "2017-12-07T00:14:53Z")

</div>

I guess an alternative would be to use something like [backbonejs](http://backbonejs.org) as your api wrapping layer and subscribe to collection events in the created() methods of the aurelia view models.

---

<div class="post-metadata">

**Author:** ![rkever](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/rkever/32/145_2.png) [@rkever](https://discourse.aurelia.io/u/rkever)\
**Post date:** [December 7, 2017, 4:07am UTC](https://discourse.aurelia.io/t/how-to-implement-global-storage/493/8 "2017-12-07T04:07:37Z")

</div>

Or you could just use EventAggregator

[http://aurelia.io/docs/fundamentals/cheat-sheet#the-event-aggregator](http://aurelia.io/docs/fundamentals/cheat-sheet#the-event-aggregator)

---

<div class="post-metadata">

**Author:** ![y-io](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/y-io/32/244_2.png) [@y-io](https://discourse.aurelia.io/u/y-io)\
**Post date:** [December 23, 2017, 4:34am UTC](https://discourse.aurelia.io/t/how-to-implement-global-storage/493/9 "2017-12-23T04:34:39Z")

</div>

@iiiyx maybe you can consider some links in this topic

> [@Best Practices for Aurelia State Management](https://discourse.aurelia.io/t/best-practices-for-aurelia-state-management/300):
>
> These articles showing different approaches for managing state: [https://www.sitepoint.com/managing-state-aurelia-with-redux/](https://www.sitepoint.com/managing-state-aurelia-with-redux/)[http://pragmatic-coder.net/using-a-state-container-with-aurelia/](http://pragmatic-coder.net/using-a-state-container-with-aurelia/)[https://github.com/axwalker/aurelia-observer-patterns/wiki/Observer-patterns-in-Aurelia](https://github.com/axwalker/aurelia-observer-patterns/wiki/Observer-patterns-in-Aurelia)
