Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequelize under Angular2 w/ Typescript

I'm brand new to Angular and just getting started on getting my head wrapped around how it works. Please, Internet, be gentle...

I've completed the Angular2 5 min Quickstart through Tour of Heroes and have that working without an issue. Now I'm trying get connectivity to my local MS SQL server as I have a SQL-based project coming where Angular2 is the required platform. I've been banging my head against the wall for days on getting Sequelize to work and could really use some help.

What I've done so far based on different things I've read:

  • Used npm to install sequelize and verified that sequelize and the dependencies of lodash, bluebird and validator all exist under node_modules
  • Downloaded bluebird.d.ts, lodash.d.ts, sequelize.d.ts and validator.d.ts from the DefinitelyTyped project on GitHub and put them in my typings folder
  • In tsConfig.json, I changed the compilerOptions --> target from es5 to es6
  • Created a simple db.component.ts file (see below)
  • Updated app.component.ts to import the db.component and added a route to it

At this point the simple page comes up, but I am unable to figure out how to get Sequelize working.

Script errors I'm seeing (based on using Visual Studio Code as my editor):

  • When I open sequelize.d.ts, there is an error on the line 'declare module "sequelize" {' stating that "Ambient modules cannot be nested other modules"
  • When I open lodash.d.ts, there are errors on lines 239 and 240 (the underscores) that states "Duplicate Identifier '_'"

I've tried a number of different approaches (guesses) on how to get sequelize to connect to my database and just cannot get anything to work. I understand that I need either (both?) an import and/or a require in the db.component.ts file, but only end up with errors either in the IDE as bad syntax or in the browser (Chrome).

I do understand that in the long run, my route/config/etc that I'm testing with here is not going to be the "right" way to do it, but I just need to get past the basic proof-of-concept that I can do something with the database before I re-engineer it (e.g. - can I connect to the database and query a table)

app.component.ts

import { Component }            from 'angular2/core';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router';

import { DashboardComponent }   from './dashboard.component';
import { HeroService }          from './hero.service';
import { HeroesComponent }      from './heroes.component';
import { HeroDetailComponent }  from './hero-detail.component';

import { dbComponent }          from './db.component';

@Component({
    selector: 'my-app',
    template: `
        <h1>{{title}}</h1>
        <nav>
            <a [routerLink]="['Dashboard']">Dashboard</a>
            <a [routerLink]="['Heroes']">Heroes</a>
        </nav>
        <router-outlet></router-outlet>
    `,
    styleUrls: ['app/app.component.css']
    directives: [ROUTER_DIRECTIVES],
    providers: [
        ROUTER_PROVIDERS,
        HeroService
    ]
})

@RouteConfig([
    {
        path: '/dashboard',
        name: 'Dashboard',
        component: DashboardComponent,
        useAsDefault: true
    },
    {
        path: '/heroes',
        name: 'Heroes',
        component: HeroesComponent
    },
    {
        path: '/detail/:id',
        name: 'HeroDetail',
        component: HeroDetailComponent
    },
    {
        path: '/sql',
        name: 'SqlTest',
        component: dbComponent
    }   
])

export class AppComponent {
  title = 'Sample App';
}

db.component.ts

/// <reference path="../typings/sequelize.d.ts" />

import { Component, OnInit }            from 'angular2/core';
import Sequelize = require('sequelize');  <-- I dont know if this is doing anything

//- This just errors out with require not being found (tds@latest installed)
//var Sequelize = require("sequelize");

//- I know this goes somewhere, but I have no idea where
//var sql = new Sequelize('dbName', 'uName', 'pw', {
//  host: "127.0.0.1",
//  dialect: 'mssql',
//  port: 1433 <-- SqlExpress
//});

@Component({
    selector: 'my-sql',
    template:`
        <h1>SQL Test</h1>
    `
})

export class dbComponent implements OnInit {

    constructor(
    ) { }

    auth() {
        console.log('auth');
        //sql.authenticate().then(function(errors) { console.log(errors) });
    }

    ngOnInit() {
        console.log('onInit');
        this.auth();
    }
}

My console.log message are coming up so I believe that I have the core functionality basically working, but I'm at a loss on what I need to do to get Sequelize functional.

There's a piece of the puzzle that I'm missing and I'm at my wits end on this. Thanks in advance for any direction...

like image 741
UncleRico Avatar asked Dec 15 '22 08:12

UncleRico


2 Answers

Ok, first off Sequelize is Javascript but I can't think of a good reason why you would ever want to use it on the front-end which angular2 is.

There are a ton of steps between having my "Tour of Heroes" Angular2 app to being able to call a database.

1: You really need to create a server, NodeJS is fantastic! You could do something like this to get started:

var express = require('express');

var http = require('http');
var path = require('path');
var bodyParser = require('body-parser');
var mysql = require('ms-sql');//Note not entirely sure if this is the correct library for MS-SQL Server I would google how to use this.

var app = express();  
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, 'public')));

So before we go much further I would like to point out that you need to have your angular app inside the public directory. You will also need to get the library for MS-SQL, and download additional packages including express and body-parser. I would start by using npm install express-generator -g, and then go to the directory and type in express myapp into the command line.

We have not quite made our server yet though!! Next we will get it working.

var server = http.createServer(app);

server.listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Then put that into the file then type it node myapp.js into the command console and you should have your server up and running!

Now we need to send it our Angular2 app.

app.get('/', function(req, res){
    res.render('index.html');
});

This says look into the public folder and find index.html and display it. This is how we start Angular2 from Node!

Now that we have our server up and running let's make a route so we can grab details of our application from ms-sql. I am going to cheat because I don't know ms-sql but in MySQL it is fairly easy. Just add this to your same node file with everything else:

app.use(

    connection(mysql,{

        host: 'localhost',//or the IP address
        user: 'root',
        password : 'myPassword',
        port : 3306, //port mysql
        database:'myDatabaseName'
    },'request')
);

Now that that's done we can finally get our data from our Server.

app.get('/api/heroes', function(req, res){
    req.getConnection(function(err,connection){

       connection.query("SELECT ID, ROLE_NAME, DESCRIPTION, ACTIVE_FLAG FROM ROLES",function(err,rows)     {

           if(err)
               console.log("Error Selecting : %s ",err );

           res.json({data:rows});

        });

     });
});

You'll notice that I am sending my rows in the function call, and sending it back with a new name -> data.

now to call it in Angular2 in my component I want to get the data with, I would call it from ngOnInit. It would be better to turn this into a service and then call the function of the service, but I won't go that deep. But you can call it like this

import { Component, OnInit }            from 'angular2/core';
import {Http} from 'angular2/http':


@Component({
    selector: 'my-sql',
    template:`
        <h1>SQL Test</h1>
         {{myData}}
    `
})

export class dbComponent implements OnInit {

    myData: any;
    constructor(public http: Http) { }


    ngOnInit() {
        this.http.get('api/heroes/').map((response => this.myData = response.json().data));
    }
}

Notice there is quite a bit of things going on here. I am implementing the class Http into my constructor so that I can call it with this.http! Also note how I am importing the Http class.

Then in ngOnInit I am taking my http class and calling my api from my server, and assigning my this.myData to my response.json().data because remember data was the name that we were passing back from our server? You don't actually need to add that, it just might make your JSON easier to deal with when you receive it.

As for Sequelize, I am not entirely sure how it works as I have not used it, but you could use that in place of how we did our MySQL stuff.

Hopefully this leads you in the right direction.

like image 135
Morgan G Avatar answered Dec 18 '22 11:12

Morgan G


As far as I know Sequelize is a orm for backend. The solution to your problem would be creating api (if you want to use Sequelize then probably use nodeJs) with which your frontend app could talk.

like image 45
kit Avatar answered Dec 18 '22 12:12

kit