How to use es6 classes in *.cshtml - asp.net-mvc

Added config files to the project (packege.json &webpack.config.json), added babel. At the moment it turns out like this: There is a directory / Scripts / build &Scripts / es6 (/main.js). When the npm run build command is run, everything builds ok (from themain.js file as indicated in the entry section of thewebpack.config.json file), the bundle.js file is created in the/ Scripts / build directory. In the above, there are no problems and everything is as it should. Now I want to use the js classes (their methods and properties) in the views (* .cshtml). How do i do this? Or need a different approach? If I write js code inmain.js, then I build it, then the code fulfills. But how do I make a function and run it (for example, by clicking a button)?
packege.json:
{
"name": "SensorDashboard",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --progress --mode='development' -p"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.2",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.9"
}
}
webpack.config.js
const path = require('path');
module.exports = {
entry: ['./Scripts/es6/main.js'],
output: {
path: path.resolve(__dirname, './Scripts/build'),
filename: 'bundle.js'
},
// IMPORTANT NOTE: If you are using Webpack 2 or above, replace "loaders" with "rules"
module: {
rules: [{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
}]
}
}
main.js:
import { Map, MyClass } from './Map';
(function () {
window.test_func = function () {
let cl = new MyClass();
cl.send("asd qweqwe");
};
})();
MyClass:
export class MyClass {
send(message) {
console.log(message);
}
}
then i runing command: npm run build, and a file was created (/Script/build/bundle.js)
then i try to use in *.cshtml:
#{Layout = null;}
...
<script src="~/Scripts/build/bundle.js"></script>
...
<div>....</div>
<script type="text/javascript">
$(document).ready(function () {
test_func(); //this work
let m = new MyClass(); //this don`t work (MyClass is not defined)
m.send("asd");
});
</script>

I think should be as simple as loading the script in your .cshtml file with your standard script tag at the bottom of the file which would look something like this:
#section Scripts {
<script src="#Url.Content("~/Scripts/build/main.js")"></script>
}
(possibly without the #Url.Content though I'm not 100% sure offhand)
You could then call a function by doing something like the following example, there are a few ways and probably depends on what your class looks like in your main.js:
#section Scripts {
<script src="#Url.Content("~/Scripts/build/main.js")"></script>
document.getElementById("myButton").onclick = function(){
let someClass = new Class();
someClass.DoSomething();
}
}
Let me know if I've misunderstood the question.
Edit:
Okay, sorry I did misunderstand.
Have a look at this link and see if it helps you? It looks like exactly what you need.
It has instructions on how to configure webpack to allow calling externally.
Looks as simple as adding these two lines to your output:
libraryTarget: 'var',
library: 'EntryPoint'
Where EntryPoint is the Name you want for the module .
So:
output: {
path: path.resolve(__dirname, 'dist/js'),
filename: 'app.bundle.js',
libraryTarget: 'var',
library: 'MyModule'
},
And that should allow you to just call
EntryPoint.send("asd qweqwe");

Related

How should TypeORM in a TypeScript project be configured so it works everywhere?

I'm struggling to find a configuration that works for TypeORM in a TypeScript project in all environments.
For example, starting with this ormconfig.js:
var dotenv = require("dotenv")
dotenv.config()
var connectionOptions = [
{
"name": "default",
"type": "postgres",
"url": process.env.DATABASE_URL,
},
{
"name": "testing",
"type": "postgres",
"url": `${process.env.DATABASE_URL}_test`,
}];
module.exports = connectionOptions
But then, when I try to start the application, I get this error:
No repository for "User" was found. Looks like this entity is not registered in current "default" connection?
So, I add the entities to the config:
var dotenv = require("dotenv")
dotenv.config()
var connectionOptions = [
{
"name": "default",
"type": "postgres",
"url": process.env.DATABASE_URL,
"entities": ["src/entity/**/*"],
},
{
"name": "testing",
"type": "postgres",
"url": `${process.env.DATABASE_URL}_test`, // TODO: fix
"entities": ["src/entity/**/*"],
}];
module.exports = connectionOptions
At this point, running the app in dev (ts-node-dev src/main.ts) works. But when I compile it and try to run the JavaScript, I get this error:
C:\Users\pupeno\Documents\Flexpoint Tech\js\exp7\backend\src\entity\User.ts:1
import {BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn} from "typeorm"
^^^^^^
SyntaxError: Cannot use import statement outside a module
It's trying to load the User.ts source file instead of the compiled User.js.
The way I'm running my app in prod is by running node build/src/main.js, the problem is that ormconfig.js is still at the top level, printing __dirname and __filename shows:
C:\Users\pupeno\Documents\Flexpoint Tech\js\exp7\backend
C:\Users\pupeno\Documents\Flexpoint Tech\js\exp7\backend\ormconfig.js
How are you supposed to configure TypeORM to work in both development and production?
Renaming my entity to User.entity.ts and setting entities this way:
var dotenv = require("dotenv")
dotenv.config()
var connectionOptions = [
{
"name": "default",
"type": "postgres",
"url": process.env.DATABASE_URL,
"entities": [__dirname + '/**/*.entity{.ts,.js}'],
},
{
"name": "testing",
"type": "postgres",
"url": `${process.env.DATABASE_URL}_test`, // TODO: fix
"entities": [__dirname + '/**/*.entity{.ts,.js}'],
}];
console.log(connectionOptions)
module.exports = connectionOptions
cause the same error, as Node tries to load a TypeScript file:
(node:19344) UnhandledPromiseRejectionWarning: C:\Users\pupeno\Documents\Flexpoint Tech\js\exp7\backend\src\entity\User.entity.ts:1
import {BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn} from "typeorm"
^^^^^^
SyntaxError: Cannot use import statement outside a module
My solution to this problem is to import models as classes instead of trying to get the glob to work. I also don't use an ormconfig.js but keep everything in TypeScript with a connection manager class. So your example rewritten for me would look like this:
import {createConnection, Connection} from "typeorm";
import {User} from "./models";
export getConnection = async (): Promise<Connection> => {
const connection = await createConnection({
name: "testing",
type: "postgres",
url: process.env.DATABASE_URL,
entities: [User]
});
return await connection.connect();
}
That can work nicely if you have a small number of models, but it doesn't scale real well. If you have many models, you can export them all from an index and then import them all from that index.
export * from "./User";
export * from "./Foo";
export * from "./Bar";
Now here's the import
import {createConnection, Connection} from "typeorm";
import * as models from "./models";
export getConnection = async (): Promise<Connection> => {
const connection = await createConnection({
name: "testing",
type: "postgres",
url: process.env.DATABASE_URL,
entities: [...Object.values(models)]
});
return await connection.connect();
}
And finally dotenv is a little simplistic for doing this work for my tastes. I recommend you check out https://github.com/lorenwest/node-config and see how you can have base config, env-specific config and envvars all play together well.
I got a similar issue. The solution is to run the app from inside the build directory, not the project directory, i.e. do cd dist and then node app.js instead of node dist/app.js.
My project structure is:
my-app-name/
-- node_modules/
-- dist/ # there go compiled JS files
-- entity/ # entities in TS
-- migration/ # migrations in TS
-- app.ts
-- tsconfig.json
-- ormconfig.json
-- package.json
# ormconfig.json
{
# database specific code is omitted
"entities": [
"./entity/*.js"
],
"migrations": [
"./migration/*.js"
]
}
# tsconfig.json
{
"files": [
"app.ts",
"entity/author.ts",
"entity/photo.ts",
"migration/1618859843962-AddAuthorToPhotos.ts"
],
"compilerOptions": {
"outDir": "dist",
"target": "esnext",
"strict": true,
"lib": [
"ES2020"
],
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"module": "commonjs",
"moduleResolution": "node"
}
}

Typescript equivalent of inline JavaScript

This may be self-evident but I'm not finding any example that informs what I'm trying to do (maybe I'm just doing it wrong). I'm adding Vue to an existing ASP.NET Core MVC application and adding the JavaScript statements directly to the page works but when I try to migrate to a TypeScript file nothing happens.
The JavaScript is:
new Vue({
el: "#productPage",
data: {
isLoading: true
},
methods: {
},
mounted () {
console.log("mounted()");
this.isLoading = false;
}
});
This works as expected. Migrating the code to a TypeScript file productPage.ts:
import Vue from 'vue';
new Vue({
el: "#productPage",
data: {
isLoading: true
},
methods: {
},
mounted () {
console.log("mounted()");
this.isLoading = false;
}
});
Which generates:
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "vue"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var vue_1 = require("vue");
var HonestyBox;
(function (HonestyBox) {
new vue_1.default({
el: "#productPage",
data: {
isLoading: true
},
methods: {},
mounted: function () {
console.log("Mounted !!!!");
this.isLoading = false;
}
});
})(HonestyBox || (HonestyBox = {}));
});
//# sourceMappingURL=productPage.js.map
And including the generated javascript file productPage.js:
<script src="~/js/productPage.js"></script>
This does nothing. Stepping through the debugger neither of the conditions in function(factory) are satisfied. The console tells me You are running Vue in development mode. but the included JavaScript fails to run. The tsconfig.json used to generate the JavaScript file:
{
"compileOnSave": true,
"compilerOptions": {
"module": "umd",
"moduleResolution": "node",
"noImplicitAny": false,
"noEmitOnError": true,
"removeComments": true,
"sourceMap": true,
"target": "es5",
"outDir": "wwwroot/js"
},
"include": [
"Typescript/**/*"
],
"exclude": [
"node_modules",
"wwwroot"
]
}
Using "module": "commonjs" results in ReferenceError: exports is not defined. I was hoping to avoid having to use Browserify or Webpack.
If I understand you correctly you add Vue in a separate script tag before your productPage.js.
This means that you can't import Vue in your TypeScript file, but you need to declare Vue so the module just assumes that Vue has been loaded already (outside of your TS module).
declare const Vue; // this replaces your Vue import statement
If you want to add a bundler later on, you need to remove your script tag which loads Vue and only go the modular approach:
Vue needs to be imported with an import statement so the bundler knows that he has to include all of Vue.
You will then have one single JS file (or if your bundler splits it: multiple JS files).

Webpacker, babel, uglifyjs-webpack-plugin - not transforming arrow functions, but only in Vue files

Running webpacker 3.5.5 (both the gem and package). This is mostly working, but in IE11 the app is broken because arrow functions do not appear to be transformed. However, inspecting the minified code it seems like the only place arrow functions aren't transformed are inside my vue components.
I think this is because my babel class properties plugin is not applying to my Vue loader somehow, but I haven't been able to come up with a solution.
Here's my .babelrc
{
"presets": [
[
"env",
{
"modules": false,
"targets": {
"browsers": [
"> 1%",
"IE 11"
],
"uglify": true
},
"useBuiltIns": true
}
]
],
"plugins": [
"syntax-dynamic-import",
"transform-object-rest-spread",
[
"transform-class-properties",
{
"spec": true
}
]
],
"env": {
"test": {
"presets": ["es2015"]
}
}
}
And here's the entirety of my environment.js file that modifies the webpack environment that webpacker ships with (vue loader is at the bottom).
const { environment } = require('#rails/webpacker');
environment.loaders.append('expose', {
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: 'jQuery'
}]
});
const webpack = require('webpack');
// append some global plugins
environment.plugins.append('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
axios: 'axios',
moment: 'moment-timezone',
_: 'lodash'
}));
// Necesary configuration for vue-loader v15
const VueLoaderPlugin = require('vue-loader/lib/plugin');
environment.plugins.append(
'VueLoaderPlugin',
new VueLoaderPlugin()
);
environment.loaders.append('vue', {
test: /\.vue$/,
loader: 'vue-loader'
});
module.exports = environment;
Edit for more info: Here is the entry point to my pack called 'wrestling'
import 'babel-polyfill';
import 'wrestling';
Then in wrestling.js...
import './styles/wrestling'
import Rails from 'rails-ujs'
Rails.start();
import wrestlingSetup from './wrestlingSetup'
wrestlingSetup();
WrestlingSetup contains the actual references to the vue files. I've cut down the file to show what a single vue import looks like within the file. All the rest are essentially the same.
import Vue from 'vue/dist/vue.esm'
// Redacted a bunch of imports, but they all look like this oen
import WrestlerCreate from './vue/wrestler_create.vue'
export default function() {
document.addEventListener('DOMContentLoaded', () => {
axiosSetup();
const app = new Vue({
el: '#app',
components: {
// Other vue components here that I've removed for simplicity
WrestlerCreate,
}
})
});
}
Here's an actual example of the Vue component
<template>
<div role="form">
<!-- other form elements -->
</div>
</template>
<script>
export default {
name: 'wrestler-create',
props: [
],
// This does not get transformed by babel
data() {
return {
loading: false,
error: false,
errorMessage: "Error, please try again later or contact support.",
first_name: '',
last_name: '',
weight_class: '',
academic_class: ''
}
},
methods: {
// removed for simplicity
}
}
</script>
For clarify sake:
Please use function() for data. I find function() gives me less trouble than arrow functions.
export default {
data: function() {
return {
message: "Hello something!",
secondMessage: "Hello world!"
};
}
}
If you really wish to use arrow function, you can write:
export default {
data: () => {
return {
message: "Hello something!",
secondMessage: "Hello world!"
};
}
}

Not able to access right node_modules path on webpack-rails

I am trying for the first time to work with angularjs with rails as the back end. I am using webpack-rails gem for the webpack configuration for managing css and other style sheets.
First I made a sample angular + rails app to display a simple text "Hello world". By default the font was in times new roman. Then I added bootstrap to the package.json file as follows.
package.json
{
"name": "shine",
"version": "0.0.1",
"license": "MIT",
"dependencies": {
"stats-webpack-plugin": "^0.4.3",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.2",
"css-loader": "^0.23.1",
"file-loader": "^0.9.0",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"bootstrap": "3.3.7"
}
}
Then I ran npm install which generated a folder named node_modules
with all the packages mentioned in the package.json in Project/node_modules path.
And webpack configuration to access access these package files is given in the
webpack.config.js
'use strict';
var path = require('path');
var webpack = require('webpack');
var StatsPlugin = require('stats-webpack-plugin');
// must match config.webpack.dev_server.port
var devServerPort = 3808;
// set NODE_ENV=production on the environment to add asset fingerprints
var production = process.env.NODE_ENV === 'production';
var config = {
entry: {
// Sources are expected to live in $app_root/webpack
'application': './webpack/application.js'
},
output: {
// Build assets directly in to public/webpack/, let webpack know
// that all webpacked assets start with webpack/
// must match config.webpack.output_dir
path: path.join(__dirname, '..', 'public', 'webpack'),
publicPath: '/webpack/',
filename: production ? '[name]-[chunkhash].js' : '[name].js'
},
resolve: {
root: path.join(__dirname, '..', 'webpack')
},
plugins: [
// must match config.webpack.manifest_filename
new StatsPlugin('manifest.json', {
// We only need assetsByChunkName
chunkModules: false,
source: false,
chunks: false,
modules: false,
assets: true
})]
};
if (production) {
config.plugins.push(
new webpack.NoErrorsPlugin(),
new webpack.optimize.UglifyJsPlugin({
compressor: { warnings: false },
sourceMap: false
}),
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('production') }
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin()
);
} else {
config.devServer = {
port: devServerPort,
headers: { 'Access-Control-Allow-Origin': '*' }
};
config.output.publicPath = '//localhost:' + devServerPort + '/webpack/';
// Source maps
config.devtool = 'cheap-module-eval-source-map';
}
module.exports = config;
And in my webpack/application.js I am calling that bootstrap package as follows.
require("bootstrap/dist/css/bootstrap.css");
console.log("Hello world!");
Now when I restart the server and reload the page I don't see any change in the font instead in the console I am getting.
Uncaught Error: Cannot find module "bootstrap/dist/css/bootstrap.css"
at webpackMissingModule
What am I doing wrong here ?
perhaps...
require('boostrap');
if that doesn't work, check to see if the file bootstrap/dist/css/bootstrap.css exists

webpackMissingModule application.js on rails with angular app

I am following the steps like given by the author.
Following is the
package.json
{
"name": "shine",
"version": "0.0.1",
"license": "MIT",
"dependencies": {
"stats-webpack-plugin": "^0.4.3",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.2",
"css-loader": "^0.23.1",
"file-loader": "^0.9.0",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"bootstrap": "3.3.7"
}
}
I am trying to change the default font to a different font by requiring the bootstrap.
My application.js looks like this
require("bootstrap/dist/css/bootstrap.css");
console.log("Hello world!");
And then I restarted the server. I see the text content are in same font-family as before nothing has changed when it should be actually a different font. And the console is giving the error as follows.
console
Uncaught Error: Cannot find module "bootstrap/dist/css/bootstrap.css"
at webpackMissingModule
webpack.config.js
// Example webpack configuration with asset fingerprinting in production.
'use strict';
var path = require('path');
var webpack = require('webpack');
var StatsPlugin = require('stats-webpack-plugin');
// must match config.webpack.dev_server.port
var devServerPort = 3808;
// set NODE_ENV=production on the environment to add asset fingerprints
var production = process.env.NODE_ENV === 'production';
var config = {
entry: {
// Sources are expected to live in $app_root/webpack
'application': './webpack/application.js'
},
output: {
// Build assets directly in to public/webpack/, let webpack know
// that all webpacked assets start with webpack/
// must match config.webpack.output_dir
path: path.join(__dirname, '..', 'public', 'webpack'),
publicPath: '/webpack/',
filename: production ? '[name]-[chunkhash].js' : '[name].js'
},
resolve: {
root: path.join(__dirname, '..', 'webpack')
},
plugins: [
// must match config.webpack.manifest_filename
new StatsPlugin('manifest.json', {
// We only need assetsByChunkName
chunkModules: false,
source: false,
chunks: false,
modules: false,
assets: true
})]
};
if (production) {
config.plugins.push(
new webpack.NoErrorsPlugin(),
new webpack.optimize.UglifyJsPlugin({
compressor: { warnings: false },
sourceMap: false
}),
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('production') }
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin()
);
} else {
config.devServer = {
port: devServerPort,
headers: { 'Access-Control-Allow-Origin': '*' }
};
config.output.publicPath = '//localhost:' + devServerPort + '/webpack/';
// Source maps
config.devtool = 'cheap-module-eval-source-map';
}
module.exports = config;
I am not able to figure out if this is npm installing issue or something else. How can I fix this.
It seems your using older version of webpack, which I infer after seeing the resolve.root property. From webpack 1 docs
The directory (absolute path) that contains your modules. May also be an array of directories. This setting should be used to add individual directories to the search path.
So when your bootstrap.css files is being resolved instead of searching node_modules, it searches in your
resolve: { root: path.join(__dirname, '..', 'webpack')}

Resources