Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 define data models for multiple modules

I'm currently starting a new project with Angular 2.0 (release Version) and I want to define some global data models/schemas. As I understand it, Angular 2 has no default way of handling pure data classes like this:

export class TestModel {
  id: number;
  name: string;
  randomAttribute: number;
  author: string;
}

So my first question regarding best practices is: Should I define such classes when working with Angular 2?

For the design and concept of my whole application I think they are necessary but I'm not sure if I'm applying the wrong way of thinking here.

This data classes are sometimes needed in multiple modules (ngModule) so my second question is Where do I place them in my app? Currently I have the following structure:

/app
   /shared
      shared.module.ts
      test.model.ts
   /module1
      module1.module.ts
      foo.component.ts
      [...]
   /module2
      module2.module.ts
      bar.component.ts
      [...]
   app.module.ts
   [...]

My first thought was to include the instruction.model.ts in the shared.module and export it in every module that imports shared.module. That doesn't seem to work because the model is not a directive, pipe or module. Is there a way to export it anyway?

The simpler solution would be to just directly import the test.model.ts file and every other shared model in every module that needs it. But this seems clunky and not convenient for multiple models.

The third possible solution I thought of was to put all shared data models in a separate folder, bundle their export in a single file like the one below and import this file in every module that needs it.

like image 411
A. Ziegler Avatar asked Oct 11 '16 15:10

A. Ziegler


People also ask

Can we declare a component in multiple modules in Angular?

Shared modules are an ideal spot to declare components in order to make them reusable. You won't have to re-import the same components in every module—you'll just import the shared module. In this guide, you will learn how to use shared modules to organize your code more effectively.

Can an Angular app have multiple modules?

The root module is the main module in an Angular application. It is generated by the Angular CLI as AppModule and bootstrapped when the application starts. Every other Angular module depends either directly or indirectly on the root module. Only one root module can exist in an Angular application.

What is @NgModule in Angular?

@NgModule takes a metadata object that describes how to compile a component's template and how to create an injector at runtime. It identifies the module's own components, directives, and pipes, making some of them public, through the exports property, so that external components can use them.

What is AppModule in Angular?

Every Angular application has at least one NgModule class, the root module, which is conventionally named AppModule and resides in a file named app. module. ts . You launch your application by bootstrapping the root NgModule.


2 Answers

So, a month later I feel confident to answer this question myself and share the methods I used to resolve some of the problems described above. Most of them stemmed from a misunderstanding of the imports and exports in Typescript and Angular2 on my part or where just design decisions.

TL;DR: Yes, model classes can be helpful. Where to place them depends on your app and your preference but absolute paths for imports help. Everything else from the question doesn't really matter.

So my first question regarding best practices is: Should I define such classes when working with Angular 2?

I didn't work with AngularJS or any JavaScript framework before I adopted Angular2 but was used to the classic MVC pattern of PHP frameworks like Laravel. So this is where this question came from. The answer for me is yes, you should. Types are the big advantage in Typescript and defining data model classes or types helps to keep the app consistent, provides autocompletion in my IDE and the typescript compiler can notify me when I mess up. Furthermore this classes enforce consistency with my relational database in the backend. Still these model classes are optional and whether to use them is a design decision or even could be considered personal opinion.

my second question is Where do I place them in my app?

Like @Sam5487 pointed out in his answer this classes are just variables or objects, like nearly everything in JavaScript. So to import them you need to make them accessible globally and just use import {SomeDumbModel} from '../../../modelfolder' to import them somewhere in your app. Of course this works from any position in the app BUT this relative paths can get very long and clunky. So the real question should have been: Can I use absolute paths for imports?. And the answer is yes, at least with the angular-cli, webpack and typescript. I don't know the solution for SystemJS or other setups. I went with a /models folder at the root of my app which can be referenced my @models/ when importing anywhere.

My first thought was to include the instruction.model.ts in the shared.module and export it in every module that imports shared.module. That doesn't seem to work because the model is not a directive, pipe or module. Is there a way to export it anyway?

The Rest of the question is just based on my misunderstanding of imports and exports in Typescript and Angular2. All the stuff about modules and exporting it doesn't matter here and is important for completely different problems. Everything else should be answered by now.

like image 77
A. Ziegler Avatar answered Oct 02 '22 17:10

A. Ziegler


If you don't want to use a Service, I would just put your global variables in a file and then export them.

Example:

//
// ===== File myGlobals.ts    
//
'use strict';

export var seperator='/';
export var add='+';
export var subtract='-';

//... whatever else you need

And to use the global variables, just import them into each file you want to use them: import globalVars = require('./myGlobals');

A2's Hero example:

// 
// ===== File heroes.component.ts    
//
import {Component, OnInit} from 'angular2/core';
import {Router} from 'angular2/router';
import {HeroService} from './hero.service';
import {HeroDetailComponent} from './hero-detail.component';
import {Hero} from './hero';
import globalVars = require('./myGlobals');

export class HeroesComponent implements OnInit {
    public heroes: Hero[];
    public selectedHero: Hero;
    // 
    //
    // Here we access the global var reference.
    //  
    public helloWorld: string="hello " + globalVars.seperator + " there";

         ...

        }
    }
like image 31
Sam5487 Avatar answered Oct 02 '22 17:10

Sam5487