Skip to content

05. Data Framework

Ali Badakhshan edited this page Apr 15, 2019 · 3 revisions

Data Framework

Data plays an important role in data-centric applications. In this type of applications, you usually retrieve data from remote-server, work with it inside the application, display it in UI components, and finally send data to the remote server. Sometimes you need to store some data on local storage and other storages like that, invalidate it on the specific condition and...

Narik Data Service has two main concepts.

  • Data Provider
  • Data Storage

Data Provider

Data Provider is a class that provides data for the system. It must inherit DataProvider interface. You can have a lot of DataProvider in your application that each of then provides data in a different way.

Currently, there are six DataProviders in Narik.

  1. RemoteDataProvider
  2. LocalStorageDataProvider
  3. SessionStorageDataProvider
  4. MemoryDataProvider
  5. StaticDataProvider
  6. ClientStorageDataProvider

Data Storage

Data Storage is a class that can store data for the system. It must inherit DataStorage interface. You can have a lot of **dataStorage ** in your application that each of then stores data in a different way and different location. Every DataStorage is also DataProvider, because DataStorage interface extends DataProvider interface.

Currently, there are four DataStorages in Narik.

  1. LocalStorageDataProvider
  2. SessionStorageDataProvider
  3. MemoryDataProvider
  4. ClientStorageDataProvider

These four classes concurrently are DataProvider and DataStorage but other two classes (RemoteDataProvider and StaticDataProvider) are only dataProvider because they don't store data.

Data Provider Service

DataProviderServices acts as a manager for all DataProviders. it collects all DataProviders and manages them. Many times it's better you work with DataProviderServices rather than with DataProvider.

Data Storage Service

**DataStorageServices **acts as a manager for all DataStorages. it collects all DataStorages and manages them. Many times it's better you work with **DataStorageServices **rather than with DataStorage.

How It Works

As said before Narik provides some DataProvider and DataStorage. But you can add new DataProviders and DataStorages.

  • Add New DataProvider

    1. Create a class that implements DataProvider.
    2. Provide it in your module providers as DATA_PROVIDER.

    Example:

        import {DataProvider,DataInfo} from "narik-infrastructure";
    
        @Injectable()
        export class MyDataProvider implements DataProvider {
            key="MyDataProvider";
            order: number;
            belongsInChain: boolean;
    
            getData(dataInfo: DataInfo): Observable<any>;
            getData<T>(dataInfo: DataInfo): Observable<T>;
            getData<T>(dataInfo: DataInfo): Observable<T> {
                ...
            }
    
    
            getDataStream(dataInfo: DataInfo): Observable<any>;
            getDataStream<T>(dataInfo: DataInfo): Observable<T>;
            getDataStream<T>(dataInfo: DataInfo): Observable<T> {
                ...
            }
    
            dataChanged(dataInfo: DataInfo | DataInfo[]): any{
                ...
            }
        }
        {
            provide: DATA_PROVIDER,
            useClass: MyDataProvider,
            multi: true
        }
  • Add New DataStorage

    1. Create a class that implements DataStorage.
    2. Provide it in your module providers as DATA_STORAGE.

    Example:

        import {DataStorage,DataInfo} from "narik-infrastructure";
    
        @Injectable()
        export class MyDataStorage implements DataPStorage {
            key="MyDataStorage";
            order: number;
            belongsInChain: boolean;
    
            getData(dataInfo: DataInfo): Observable<any>;
            getData<T>(dataInfo: DataInfo): Observable<T>;
            getData<T>(dataInfo: DataInfo): Observable<T> {
                ...
            }
    
    
            getDataStream(dataInfo: DataInfo): Observable<any>;
            getDataStream<T>(dataInfo: DataInfo): Observable<T>;
            getDataStream<T>(dataInfo: DataInfo): Observable<T> {
                ...
            }
    
            dataChanged(dataInfo: DataInfo | DataInfo[]): any{
                ...
            }
    
            clear(): Observable<any>{
                ...
            }
    
            removeItems(items: DataInfo[]): Observable<any>
            {
                ...
            }
    
            applyValidity(dataItems: { dataInfo: DataInfo; validDate: Date }[])
            {
                ...
            }
    
            addItem(dataItmes: { dataInfo: DataInfo; data: any }[]): Observable<any>
            {
                ...
            }
        }
        {
            provide: DATA_STORAGE,
            useClass: MyDataStorage,
            multi: true
        }

    If you want to provide your class as DATA_STORAGE and DATA_PROVIDER be careful to provide it with useExisting to have one instance for them.

       {
           provide: MyDataStorage,
           useClass: MyDataStorage
       },
       {
           provide: DATA_STORAGE,
           useExisting: MyDataStorage,
           multi: true
       },
       {
           provide: DATA_PROVIDER,
           useExisting: MyDataStorage,
           multi: true
       }
  • Use Data Provider To Use DataProvider, you can work with specified DataProvider or use DataProviderService. Narik suggests you use DataProviderService.

    Example 1:

    import {
        DataInfo,
        DataProviderService,
        DataOption
    } from "narik-infrastructure";
    
    export  class TestData
    {
        constructor(private dataProviderService: DataProviderService) {
        }
    
        SomeMethod()
        {
            // It emits only once
            this.dataProviderService.getData(
                {
                    "datakey":"some-data-key",
                    "dataProviderKey":"MyDataProvider"
                }
            ).subscribe(...);
    
            // It emits whenever data changed
            this.dataProviderService.getDataStream(
                {
                    "datakey":"some-data-key",
                    "dataProviderKey":"MyDataProvider"
                }
            ).subscribe(...);
        }
    }

    Example 1:

    <narik-select label="{{ 'font' | translate }}" [dataKey]="'fonts'" [(ngModel)]="model.font"
    name="font" required></narik-select>
  • Use Data Storage
    To Use DataStorage, you can work with specified DataStorage or use DataStorageService. Narik suggest you to use DataStorageService.
    Don't forget every DataStorage is also DataProvider and can be used like DataProvider.

    Example

     import {
          DataInfo,
          DataStorageService,
          DataOption
      } from "narik-infrastructure";
    
      export  class TestData
      {
    
          @Input()
          tokenStorage:sting="localStorage";
    
          constructor(private dataStorageService: DataStorageService) {
          }
    
          init()
          {
              this.dataStorageService
              .getData(this.tokenStorage, {
                  dataKey: "auth-token"
              })
              .subscribe(token => {
                  if (token) {
                      this._token = token;
                      this.dataStorageService
                          .getData(this.tokenStorage, {
                              dataKey: "current-user"
                          })
                          .subscribe(result => {
                              this._currentUserValue = result;
                              this._currentUserSubject.next(this._currentUserValue);
                          });
                  }
              });
          }
    
          login ()
          {
              .....
              ....
              this.dataStorageService
              .addData(this.tokenStorage, [
                  {
                      dataInfo: {
                          dataKey: "auth-token"
                      },
                      data: result.token
                  },
                  {
                      dataInfo: {
                          dataKey: "current-user"
                      },
                      data: result.loginedUser
                  }
              ]).subscribe(() => {
                  resolve(result);
              });
    
          }
      }
You can’t perform that action at this time.