Should I have API models and UI models in an Angular app - asp.net

I am working on an App where I am using .Net Core as my API, SQL Server as database, and Angular for the UI. I am following a course that does not provide much explanation on why he does what he does so I decided to post a couple of questions here after Googling did not help. In the angular app, the instructor uses an api-model (interface) to fetch the data from the API in a service using an http method, and then in the component .ts file he sets the observable response to a ui-model to use in the template.
Is it a standard or good practice to use api and ui models instead of just one in the front-end? - I am using DTOs and DAOs in the API and have an understanding of the why but not clear there is a benefit to doing this in the Front-end.
Is there an advantage to using an interface instead of a class when creating models? So far this is the first example I've seen of someone using an interface in Angular when creating a model.
UI and API models are identical. He basically puts the API fetched data into an API model and dumps it into a UI model to use in the template

When you say models I'm assuming you just mean defining a schema for your data (type, interface, or class). The main purpose of them is to make sure you as a developer do not make mistakes. If you have defined a data type and you try to access a property that doesn't exist, the typescript compiler will catch this. Another example is if you try to do some math with the id parameter, the compiler will tell you that's a string, not a number.
Yes, you should define your schemas on both sides, or you'll be making dumb mistakes like that all over the place. Plus this way you get intellisense and code completion.
As for the difference between interfaces and classes, there are three ways to define a data type in typescript:
Types
This is simply an object type where each property type is defined. Types do not support inheritance, and they do not have constructors.
type Fruit = {
name: string;
color: string;
weight: number;
similarFruits: Fruit[];
decompose: () => RottenFruit;
};
Interfaces
Interfaces are essentially the same as types but they can extend eachother, and classes can implement them.
interface Fruit {
name: string;
color: string;
}
interface Banana extends Fruit {
eat: () => string;
}
class BigYellowBanana implements Banana {
name: string;
color: string;
eat: () => string;
constructor() {
this.name = 'Big Yellow Banana';
this.color = 'Yellow';
this.eat = () => 'mmmm banana';
}
}
Classes
Classes are a whole other can of worms because they have all the functionality of an object oriented language. Most notably, a constructor that can be called with the new keyword.
class BigBanana extends SmallBanana implements Banana {
name: string;
color: string;
private eatMessage = 'mmmm banana';
constructor(color: string) {
this.color = color;
this.name = `Big ${color} Banana`;
}
eat() {
return this.eatMessage;
}
}
const greenBanana = new BigBanana('Green');
I apologize for my dumb examples.

Related

How best to include tenant in Angular 2 Routing

I'm pretty new to Angular 2 and a little confused as to whether I'm approaching this problem in the right way. I'm writing a multi-tenant app and I would like all the url's to start with the tenant id. An example would be: https://example.org/tenant-1/product/list or https://example.org/tenant-2/product/list. This seems like quite a simple and well solved problem, but I'm having trouble finding a recommended way of achieving this.
So far I have created a routing service:
#Injectable()
export class RoutingService {
public ClientId: string = null;
constructor() {}
getRoute(path: string): string {
if (!this.ClientId) {
// For deep-linking
this.ClientId = window.location.pathname.split('/')[1];
}
return '/' + this.ClientId + path;
}
}
The user is presented a list of tenants and selects one. This sets the ClientId on the RoutingService.
Within each component, I'm importing this RoutingService in the constructor and the HTML uses it to create the route:
[routerLink]="[routingService.getRoute('/product/list')]
Is there a better way of doing this?
I am in a similar situation as yourself and it seems like pulling it from a service is the way to do it currently because of component encapsulation/isolation:
Angular 2: How to pass route parameters to subroute?
https://angular.io/docs/ts/latest/guide/router.html#!#route-parameters
Instead of creating a RouteService or RouteParamService, I am baking it into my AuthService since tenant is part of authentication. Other than tenant the route parameters work fine in isolation in my case.

angular2 data binding by using reference data types in a service

So I recently posted angular2 data binding between service and component properties and Thierry pointed out something interesting.
If I have a reference datatype like an array or an object stored in a service (singelton) and create references in various components pointing to it, the view will update for all components when the object is updated from anywhere (and it works!).
In my case, I'm building a small forum where thread objects will need to be displayed/viewed in various components at the same time(e.g. preview, mainview, dashboard...). For updating/editing text fields this might come really handy.
Now i'm wondering if this is save to use?
You need to leverage observables on which components will subscribe to be notified when fields have changed.
Something like that:
export class Service {
name = "Luke";
nameUpdated = new Subject();
getName() {
return this.name;
}
updateName() {
this.name = 'Luke1';
this.nameUpdated.next(this.name);
}
}
and in the component:
this.name = this._service.name;
this._service.nameUpdated.subscribe(name => {
this.name = name;
});
See this plunkr: https://plnkr.co/edit/CRE92tdCsteoS2MVeGfh?p=preview

using export in alloy controller versus attaching functions directly to the '$' scope

here is the code of an alloy controller written in two different ways. Although the both work the same, Which one might be best practice?
example 1 of controller.js:
var currentState = true;
$.getState = function(){
return currentState;
}
example 2 of controller.js:
var currentState = true;
exports.getState = function(){
return currentState;
}
Titanium is based on the CommonJS framework. The exports variable is a special variable used typically to expose a public API in a class object. So when you want to expose a method of doSomething() on the MyModule.js class you would use the exports variable like this:
exports.doSomething() = function(args) {
//Some really cool method here
};
Then reference that class using
var myModule = require('MyModule');
myModule.doSomething();
However when referencing a view object the typical way to reference the is using the $. shortcut. You can see they prefer that method in the official documentation.
http://docs.appcelerator.com/platform/latest/#!/guide/Alloy_XML_Markup
The $ variable holds a reference to your controller instance. It also contains some references to all indexed views (understand, views for which you supplied an index in you xml markup).
Both ways are strictly equivalent as, during the compilation, Alloy will merge the content of the exports with your controller referenced in $. Adding them directly to the instance won't change a thing.
Neverthless, developers are used to see the public API as the set of functions exported via the special variable exports; Thus, I will recommend to keep using it in a clean and clear way (for instance, defining your functions in your module scope, and only expose them at the end or beginning of your controller).
function myFunction1 () { }
function myFunction2 () { }
function myFunction3 () { }
exports.myFunction1 = myFunction1;
exports.myFunction3 = myFunction3;
Thereby, your API is quite clear for people diving into your source code. (A readMe file is also highly recommended :) ).

Flex: AMF and Enum Singletons – can they play well together?

I'm using Python+PyAMF to talk back and forth with Flex clients, but I've run into a problem with the psudo-Enum-Singletons I'm using:
class Type {
public static const EMPTY:Type = new Type("empty");
public static const FULL:Type = new Type("full");
...
}
When I'm using locally created instances, everything is peachy:
if (someInstance.type == Type.EMPTY) { /* do things */ }
But, if 'someInstance' has come from the Python code, it's instance of 'type' obviously won't be either Type.EMPTY or Type.FULL.
So, what's the best way to make my code work?
Is there some way I can control AMF's deserialization, so when it loads a remote Type, the correct transformation will be called? Or should I just bite the bullet and compare Types using something other than ==? Or could I somehow trick the == type cohesion into doing what I want?
Edit: Alternately, does Flex's remoting suite provide any hooks which run after an instance has been deserialized, so I could perform a conversion then?
Random thought: Maybe you could create a member function on Type that will return the canonical version that matches it?
Something like:
class Type {
public static const EMPTY:Type = new Type("empty");
public static const FULL:Type = new Type("full");
...
// I'm assuming this is where that string passed
// in to the constructor goes, and that it's unique.
private var _typeName:String;
public function get canonical():Type {
switch(this._typeName) {
case "empty": return EMPTY;
case "full": return FULL;
/*...*/
}
}
}
As long as you know which values come from python you would just convert them initially:
var fromPython:Type = /*...*/
var t:Type = fromPython.canonical;
then use t after that.
If you can't tell when things come from python and when they're from AS3 then it would get pretty messy, but if you have an isolation layer between the AS and python code you could just make sure you do the conversion there.
It's not as clean as if you could control the deserialization, but as long as you've got a good isolation layer it should work.

Creating Type Safe Collections in Flex

I'm trying to create a collection class in Flex that is limited to housing a specific type of data that i am using (an interface). I have chosen not to extend the ArrayCollection class as it's too generic and doesn't really give me the compile time safety that i'm after. In it's simplistic form my collection contains an array and i manage how objects are added and removed, etc.
What i really want to be able to do is use these collections in for each loops. It definitely doesn't seem as straight forward as say c# where you just implement IEnumerable and IEnumerator (or just using the generic Collection). Is there a way to do this in action script and if so any info on how it is achieved?
Cheers
You need to extend the Flash Proxy class. Extending Proxy allows you to alter how 'get' and 'set' work, as well as 'for..in' and 'for..each' loops. You can find more details on the Livedocs.
Here's an example for your issue:
package
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public class EnumerableColl extends Proxy
{
private var _coll:Array;
public function EnumerableColl()
{
super();
_coll = [ 'test1', 'test2', 'test3' ];
}
override flash_proxy function nextNameIndex( index:int ):int
{
if ( index >= _coll.length ) return 0;
return index + 1;
}
override flash_proxy function nextValue( index:int ):*
{
return _coll[ index - 1];
}
}
}
Take a look at Vector<>. That is about as best as you can go for a typed collection in Flex (4 onwards). However, you will need to implement your own class otherwise. One way, it seems, is to use the Iterator Pattern.
Also, take a look at this SO post.

Resources