3

I am learning ES 6 syntax of classes. I come from a C# background, so I apologize if my terminology isn't correct. Or, if I'm doing something that looks odd.

I'm building a web app as a learning exercise. It's built on Node and Express. I have some routes defined like this:

'use strict';

module.exports = function() {
    const app = this;

    app.use('/blog', function(req, res) {
        console.log('loading blog postings');        
        res.render('blog', {}); 
    });

    app.use('/', function(req, res) {
        console.log('looking up: ' + req.path);
        res.render('home', {});
    });
};

I'm trying to put some viewModels behind these views. So, I have a directory called viewModels. That directory has these files:

index.js
blog.js
home.js

The files currently, probably inaccurately, look like this:

index.js

'use strict';

module.exports = function() {
  const HomeViewModel = require('./home);
  const BlogViewModel = require('./blog);
};

blog.js

export default class BlogViewModel {
    constructor() {
        this.title = 'My Blog';
    }
}

home.js

export default class HomeViewModel {
    constructor() {
        this.title = 'Home';
    }
}

My thought, was that I could use index.js as a way to define my package or namespace. Then, in my routing code, I could do something like this:

'use strict';

module.exports = function() {
    const app = this;
    const ViewModels = require('../viewModels/index');

    app.use('/blog', function(req, res) {
        console.log('loading blog postings');
        let viewModel = new ViewModels.BlogViewModel();
        res.render('blog', viewModel); 
    });

    app.use('/', function(req, res) {
        console.log('looking up: ' + req.path);
        let viewModel = new ViewModels.HomeViewModel();
        res.render('home', viewModel);
    });
};

However, when I attempt this, I get some runtime errors that say "Error: Cannot find module '../viewModels/index'". This implies that I'm not setting up my module properly. But, it looks like I am what am I doing wrong?

JQuery Mobile
  • 6,221
  • 24
  • 81
  • 134
  • You should not mix commonjs with ES6 modules. – Bergi Apr 04 '16 at 14:47
  • @Bergi - So, what is the recommended approach? I'm trying to learn this stuff and there are so many examples out there. It's hard to know what's a good approach, what's a poor approach, and what was done simply because of an approach of another framework that is depended on is using. – JQuery Mobile Apr 04 '16 at 14:49
  • I'd recommend [this syntax](http://stackoverflow.com/a/34072770/1048572) for your `index.js`. – Bergi Apr 04 '16 at 14:54

2 Answers2

3

Your index.js file is incorrect, you don't export ViewModels from there. Change it to this:

'use strict';

module.exports = {
  HomeViewModel: require('./home'),
  BlogViewModel: require('./blog')
};

And ... viewModels it's good for C#, but not for Node.js. In node it should be just models, IMO.

Update:

Node.js doesn't completely support all ES6 features, especially new modules declaration: https://nodejs.org/en/docs/es6/. You should use the standard CommonJs module declaration to export your function:

'use strict';

class HomeViewModel {
  constructor() {
    this.title = 'Home';
  }
}

module.exports = HomeViewModel;
alexmac
  • 19,087
  • 7
  • 58
  • 69
  • it doesnt matter, the problem is he didnt invoke the function, but that also a solution – The Reason Apr 04 '16 at 14:17
  • even he will invoke the function, him code won't be working. He defines consts in a function, which are invisible outside of it. – alexmac Apr 04 '16 at 14:19
  • @AlexanderMac When I use that approach though, the `let viewModel = new ViewModels.HomeViewModel(); ` line throws `error: Route: / - ViewModels.HomeViewModel is not a function` – JQuery Mobile Apr 04 '16 at 14:42
  • Node.js doesn't completely support all ES6 features, especially new modules declaration: [https://nodejs.org/en/docs/es6/](https://nodejs.org/en/docs/es6/). Use the standard CommonJs module declaration to export your function: `module.exports = HomeViewModel;`. – alexmac Apr 04 '16 at 14:55
  • @AlexanderMac does the `module.exports = HomeViewModel;` approach that you mention replace the line in your answer? Or, is it after the last semi-colon in your answer? – JQuery Mobile Apr 04 '16 at 15:01
0

Actually, I am not really sure what you want to ask. If I answered wrong stuff, just never mind.

First, the reason why you get error Error: Cannot find module '../viewModels/index' is because you put two dots there. It should be just one dot means start from here. However, I am not sure if this is the problem. I wanted to ask where you put routing code, but I do not have permission to comment yet. (Ahhhh.... Stack overflow you kidding me...)

Second, here is the proper way to export a class in ES6.

For example:

AClass.js

'use strict';
//This module can be used within the class. However, you cannot use it in another file.
const AModule = require('AModule');
//The class name used here just for debug output.
module.exports = class AClass {
  constructor(startValue) {
    //Not like C#. JavaScript does not define private or public.
    this.value = startValue;
  }
  method(incValue) {
    this.value += incValue;
    AModule(); //Just show you can use this module within the class;
  }
}

main.js

'use strict';
//You need to put a ./ before the path if you are include another module made by yourself.
//You do not need it for a npm module.
const AClass = require('./AClass.js');
//Now you just required the class of the AClass, you still need to new one;
var aClass = new AClass(500);
//After new one, you can call its method.
aClass.method(30);
//You can access its property by a dot;
console.info(aClass.value); //530

This is the 100% work way to create a class in ES6.

Here is detailed documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

Anyways, classes in JavaScripts are just like functions, and a function's prototype will be its methods. new Class() is just create a object, run the function Class with object as this (Same as Class.bind(obj, parameters)), then link the new object's constructor property to the function used.

module.exports = xxx is just make the xxx the value of this module. For instance, if you module.exports = 'Hello'; and console.info(require('module'));, you will get Hello.

SCLeo
  • 353
  • 3
  • 14