React, Babel + Eslint Configuration

If you want to configure your npm package to have JavaScript static code analysis then you will need to configure some form of js linter. For the purposes of this demo I will use eslint.

Before We Begin:

Packages:

Package Installations:

  1. npm install --save-dev babel
  2. npm install --save-dev babel-core
  3. npm install --save-dev babel-loader
  4. npm install --save-dev babel-preset-es2015
  5. npm install --save-dev babel-eslint //OPTIONAL
  6. npm install --save-dev eslint
  7. npm install --save-dev eslint-loader
  8. npm install --save-dev eslint-plugin-react
  9. npm install --save-dev uglifyjs-webpack-plugin

Webpack.config.js:

Webpack 3 Plugins

Add “NoEmitOnErrorsPlugin” to ensure that emitting doesn’t occur if errors are encountered.

Add “UglifyJsPlugin” to minimize your js

Add “AggressiveMergingPlugin” to get more aggressive chunk merging.

Don’t forget the loaders for babel and eslint.

  1. const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
  2.  
  3. #Under module.exports add
  4. plugins: [
  5. new webpack.NoEmitOnErrorsPlugin(),
  6. new UglifyJsPlugin(),
  7. new webpack.optimize.AggressiveMergingPlugin()
  8. ],
  9. module: {
  10. loaders: [
  11. {
  12. enforce: "pre",
  13. test: /\.jsx?$/,
  14. exclude: /(node_modules|thirdparty)/,
  15. loader: "eslint-loader",
  16. },
  17. {
  18. test: /\.jsx?$/,
  19. exclude: /(node_modules)/,
  20. loader: "babel-loader",
  21. query: {
  22. presets: ["es2015","react"],
  23. }
  24. },
  25. ]
  26. }
  27.  
  28.  

.eslintrc

You can set anything in your .eslintrc file. Here are just some that I use. All the rules starting with “react” are from “eslint-plugin-react” package.

  1. {
  2. "parser": "babel-eslint",
  3. "env": {
  4. "browser": true,
  5. "mocha": true,
  6. "es6": true
  7. },
  8. "globals": {
  9. "require": true
  10. },
  11. "plugins": [
  12. "react"
  13. ],
  14. "rules": {
  15. "new-cap": 0, //disabled
  16. "strict": 0, //disabled
  17. "semi": [2, "always"], //semi-colon required
  18. "no-underscore-dangle": 0, //no underscores before and after off
  19. "no-use-before-define": 1, //Make sure you define then use
  20. "eol-last": 0, //File doesn't need a newline at end
  21. "no-trailing-spaces": [2, { skipBlankLines: true }],
  22. "no-unused-vars": [1, {"vars": "all", "args": "none"}],
  23. "quotes": [
  24. 2,
  25. "double"
  26. ],
  27.   "jsx-quotes": [2, "prefer-double"], //Must use double quotes
  28. "react/jsx-boolean-value": 1, //warning when no value is set for boolean
  29. "react/jsx-no-undef": 2, //error: undeclared variables
  30. "react/jsx-uses-react": 1, //Warn: Prevent incorrectly unused
  31. "react/jsx-uses-vars": 1, //Warn: Prevent unused variables
  32. "react/no-did-mount-set-state": 0, //Off: Prevent setState in componentDidMount
  33. "react/no-did-update-set-state": 0, //Off: Prevent setState in componentDidUpdate
  34. "react/no-multi-comp": 1, //Warn: Prevent only one component per file
  35. "react/no-unknown-property": 1, //Warn: Prevent unknown DOM
  36. "react/react-in-jsx-scope": 1, //Warn: Prevent missing React
  37. "react/self-closing-comp": 1 //Warn: Prevent extra closing tags
  38. }
  39. }

.eslintignore

Use this file to ignore any files or folders.

  1. app/folder/**

.babelrc

This is the config file for babel.

  1. {
  2. "presets": [ "es2015" ]
  3. }

Package.json

If you want to run eslint from npm then you have to modify your package.json with the following line. –ext is what extension you want to test against.

If you want a third party to run reports on your eslint then add to the end “-f checkstyle > eslint.xml

  1. "scripts": {
  2. "eslint": "eslint app --ext .jsx --ext .js"
  3. }

Django: React Website

In this tutorial I will demonstrate how to create a Django + React website using Django 2.0. You must have Eclipse installed before you continue. If you have it already installed and configured you can continue on. We will require Postgres 9.4, nodejs before you continue. You can get Nodejs from here. You can get Postgres 9.4 from here.

Pip Django Install:
  1. pip install django
  2. pip install django-webpack-loader
Django Version:

If you are not sure what version you are running do the following

  1. python -c "import django; print(django.get_version())"
Eclipse Create Project:

 

 

 

 

 

 

Eclipse Setup Project:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Eclipse Django DB Settings:

 

 

 

 

 

 

 

 

 

 

 

 

 

Eclipse Django Setup Successful:

Once you click “Finish” your project will look like the following.

 

 

 

Folder Structure:
  • Under djangoApp project.
  • folder: static
  • folder: djangoApp
    • folder: templates
      • file: index.html
      • folder: base
        • file: base.html
  • folder: assets
    • folder: bundles
    • folder: js
      • file: index.jsx
Node:

Inside the djangoApp application do the following

  1. npm init
  2. npm install --save-dev jquery react react-dom webpack webpack-bundle-tracker babel-loader babel-core babel-preset-es2015 babel-preset-react
  3. npm install create-react-class --save
webpack.config.js:
  1. var path = require('path')
  2. var webpack = require('webpack')
  3. var BundleTracker = require('webpack-bundle-tracker')
  4.  
  5. module.exports = {
  6. //the base directory (absolute path) for resolving the entry option
  7. context: __dirname,
  8. //the entry point we created earlier. Note that './' means
  9. //your current directory.
  10. entry: {
  11. "index": [path.resolve(__dirname, "./assets/js/index.jsx")],
  12. },
  13. output: {
  14. path: path.resolve('./assets/bundles/'),
  15. filename: "[name]-[hash].js",
  16. },
  17. plugins: [
  18. //tells webpack where to store data about your bundles.
  19. new BundleTracker({filename: './webpack-stats.json'}),
  20. //makes jQuery available in every module
  21. new webpack.ProvidePlugin({
  22. $: 'jquery',
  23. jQuery: 'jquery',
  24. 'window.jQuery': 'jquery'
  25. })
  26. ],
  27. module: {
  28. loaders: [
  29. {
  30. test: /\.jsx?$/,
  31. exclude: /(node_modules)/,
  32. loader: 'babel-loader',
  33. query: {
  34. presets: ['react','es2015']
  35. }
  36. }
  37. ]
  38. }
  39. }
djangoApp\Settings.py:

Installed Apps

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'webpack_loader',
  9. ]

Add/Edit the following template directive

  1. TEMPLATES = [
  2. {
  3. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  4. 'DIRS': [os.path.join(BASE_DIR, 'djangoApp', 'templates'),],
  5. 'APP_DIRS': True,
  6. 'OPTIONS': {
  7. 'context_processors': [
  8. 'django.template.context_processors.debug',
  9. 'django.template.context_processors.request',
  10. 'django.contrib.auth.context_processors.auth',
  11. 'django.contrib.messages.context_processors.messages',
  12. ],
  13. },
  14. },]

Add the following static directive

  1. STATIC_URL = '/static/'
  2.  
  3. STATICFILES_DIRS = [
  4. os.path.join(BASE_DIR, 'assets'),
  5. ]

Modify DATABASES

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.postgresql_psycopg2',
  4. 'NAME': 'YOUR_DB_NAME',
  5. 'USER': 'YOUR_USER',
  6. 'PASSWORD': 'YOUR_PASSWORD',
  7. 'HOST': 'localhost',
  8. 'PORT': 5432
  9. }
  10. }

Webpack Loader

  1. WEBPACK_LOADER = {
  2. 'DEFAULT': {
  3. 'BUNDLE_DIR_NAME': 'bundles/',
  4. 'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
  5. }
  6. }
djangoApp\views.py:

We will create our index page view. Notice the third dict. Those are variables passed to the template to make our site dynamic

  1. from django.shortcuts import render
  2.  
  3. def index(request):
  4. return render(request, 'index.html', {'title': 'Index Page', 'script_name': 'index'})
djangoApp\urls.py:

Add the following imports

  1. from django.conf.urls import url
  2. #This is the index view we created above
  3. from djangoApp.views import index
  4.  
  5. urlpatterns = [
  6. url(r'^$', index, name='index'),
  7. path('admin/', admin.site.urls),
  8. ]
djangoApp\templates\base\base.html:

Let’s setup our base template and setup our blocks that the other templates will inherit from.

  1. <html>
  2. <head>
  3. <title>{% block title %}{% endblock %}</title>
  4. </head>
  5. <body>
  6. {% block content %}
  7. {% endblock %}
  8. </body>
  9. </html>
djangoApp\templates\index.html:

The important parts here are the extends otherwise your base.html template won’t be inherited. As well the {% with %} and title variable makes our template dynamic and allows us to incorporate react in our site.

  1. {% extends "base/base.html" %}
  2. {% load render_bundle from webpack_loader %}
  3. {% load staticfiles %}
  4. {% block title %}
  5. {{title}}
  6. {% endblock %}
  7. {% block content %}
  8. <div id="container"></div>
  9. {% with script=script_name %}
  10. {% render_bundle script 'js' %}
  11. {% endwith %}
  12. {% endblock %}
assets\js\index.jsx:

This is our react class.

  1. var React = require('react');
  2. var ReactDOM = require('react-dom');
  3. var createReactClass = require('create-react-class');
  4.  
  5. var App = createReactClass({
  6. render: function() {
  7. return (
  8. <h1>
  9. React App Page
  10. </h1>
  11. )
  12. }
  13. });
  14.  
  15. ReactDOM.render(<App />, document.getElementById('container'));
Database Setup/Migration:

For this tutorial we used postgres. At this time please make sure you create your djangoApp db and user you specified in the settings.py file. Then run the following commands in order.

  1. #Migrates the auth
  2. python manage.py migrate auth
  3. #migrates the rest
  4. python manage.py migrate
  5. #Create the user for accessing the django admin ui
  6. #This will ask you for user names and passwords. Don't make it the same as in your settings.py file.
  7. python manage.py createsuperuser
Start Server:
  1. webpack -p
  2. python manage.py runserver

Your site is now running at http://localhost:8000.

Your admin site is now running at http://localhost:8000/admin/.

 

References:

I used this video as a guideline to get the project started. However some didn’t work right and needed to adjust and made adjustments to require just one template, etc.

React: Leaflet Markers

This entry is part 9 of 9 in the series React: Leaflet

In this tutorial I will demonstrate how to add a marker to the map. Refer to the documentation for more information.

Before We Begin:

Text:

LayerGroup onAdd Method

  1. //Define the marker. Since this is text based their is no icon but instead a divIcon
  2. this.textMarker = L.marker([20.5, -0.09],{
  3. icon: L.divIcon({
  4. iconSize: [100,16],
  5. iconAnchor: [22, 30],
  6. className: "",
  7. }),
  8. zIndexOffset: 75,
  9. });
  10.  
  11. //Sets the text
  12. this.textMarker.options.icon.options.html = "This is my text";
  13.  
  14. //Adds the text marker to the layer
  15. this.addLayer(this.textMarker);

LayerGroup onRemove Method

  1. //Remove the text marker you just added
  2. this.removeLayer(this.textMarker);

Results: Now you will see as you turn the layer on and off from the context menu the text will show or hide.

Icon:

Import Image:

  1. import myImagefrom "../images/myImage.png";

Create Icon/Marker onAdd Method

  1. //Define the icon you will be using
  2. var myIcon = L.icon({
  3. iconUrl: myImage,
  4. iconSize: [75, 75], // size of the icon
  5. iconAnchor: [22, 94], // point of the icon which will correspond to marker's location
  6. });
  7.  
  8. //Define the icon based marker
  9. this.marker = L.marker([20.5, -40.09],{
  10. icon: myIcon,
  11. opacity: 0.7,
  12. zIndexOffset: 30
  13. });
  14.  
  15. //Adds the icon marker to the layer
  16. this.addLayer(this.marker);

onRemove Method

  1. //Remove the marker you just added
  2. this.removeLayer(this.marker);

Results: Now you will see as you turn the layer on and off from the context menu the icon will show or hide.

Set Latitude/Longitude:

You can set the latitude and longitude in one of two ways.

  1. //Set the latitude and longitude
  2.  
  3. //Method 1:
  4. L.marker([20.5, -0.09])
  5.  
  6. //Method 2:
  7. this.textMarker.setLatLng([20.5, -0.09]);

Event(s):

onClick

  1. marker.on("click", function(e) {
  2. var marker = e.target;
  3. //Do my work here
  4. }.bind(this));

MouseOver

  1. marker.on("mouseover", function(e) {
  2. var marker = e.target;
  3. //Do my work here
  4. }.bind(this));

MouseOut

  1. marker.on("mouseout", function(e) {
  2. var marker = e.target;
  3. //Do my work here
  4. }.bind(this));

Popup:

BindPopup

  1. marker.bindPopup(L.popup(),{
  2. offset: L.point(0,-10) //You can add an offset if you want to
  3. });

OpenPopup

Let’s say you want to open the popup during a mouseover event.

  1. marker.on("mouseover", function(e) {
  2. var marker = e.target;
  3.  
  4. //Set the content to display in the popup
  5. marker.setPopupContent("My Text");
  6. //Now open the popup
  7. marker.openPopup();
  8. }.bind(this));

ClosePopup

Let’s say you want to open the popup during a mouseout event.

  1. marker.on("mouseout", function(e) {
  2. var marker = e.target;
  3. //Close the popup now
  4. marker.closePopup();
  5. }.bind(this));

React: Leaflet Icon

This entry is part 8 of 9 in the series React: Leaflet

In this tutorial I will demonstrate how to add an icon to the map. Refer to the documentation for more information.

Before We Begin:

Create Folders/Files:

  • app
    • folder: leaflet
      • folder: images
        • file: yourimage.png

Import Image(s):

  1. import yourimage from "../images/yourimage.png";

Create Icon:

  1. var myIcon = L.icon({
  2. iconUrl: plusimg,
  3. iconSize: [75, 75], // size of the icon
  4. iconAnchor: [22, 94], // point of the icon which will correspond to marker's location
  5. });

Add to Map:

[51.5, -0.09] refers to the position on the map you want to add it to. Refer to the marker tutorial for further information on markers.

  1. L.marker([51.5, -0.09], {icon: myIcon}).addTo(this.map);

React: Leaflet Control

This entry is part 7 of 9 in the series React: Leaflet

In this tutorial I will demonstrate how to add a control to the map. Refer to the documentation for more information.

Before We Begin:

LayerControl

You can now do anything you want to do here.

  1. var MyControl = L.Control.extend({
  2. onAdd: function (map){
  3. //Reference to the map
  4. this._map = map;
  5.  
  6. //This is the container to return so it is available on the map
  7. var container = L.DomUtil.create("div");
  8. return container;
  9. },
  10. onRemove: function(){
  11. //Removes the control
  12. L.Control.prototype.onRemove.call(this);
  13. this._map = null;
  14. }
  15. });

Add Control to Map

The options you add in the class definition are the options that the control gets.

  1. var myControl = new MyControl({ position: "bottomright"});
  2. myControl.addTo(this.map);

React: Leaflet LayerGroup

This entry is part 6 of 9 in the series React: Leaflet

In this tutorial I will demonstrate how to add a layer group control. Refer to the documentation for more information.

Before We Begin:

LayerGroup

You can now do anything you want to do here.

  1. var MyLayerGroup = L.LayerGroup.extend({
  2. onAdd: function(map) {
  3. //Reference to the map
  4. this._map = map;
  5. },
  6. onRemove: function(){
  7. //Removes the layer
  8. L.LayerGroup.prototype.onRemove.call(this, map);
  9. },
  10. initialize: function (options) {
  11. L.LayerGroup.prototype.initialize.call(this);
  12. //The options sent in from initialisation
  13. L.Util.setOptions(this, options);
  14. }
  15. });

Add LayerGroup to Map

  1. var myLayerGroup = new MyLayerGroup();
  2. myLayerGroup.addTo(this.map);

Overlay

If you want to add the layergroup to overlays menu.

  1. this.layerControl.addOverlay(myLayerGroup, "My Layer Group");

React: Leaflet DomEvent

This entry is part 5 of 9 in the series React: Leaflet

In this tutorial I will demonstrate how to add events to your html control. Refer to the documentation for more information.

Before We Begin:

OnClick

  1. L.DomEvent.on(htmlControl, "click", (e) => {
  2. //Do your work here
  3. });

 

 

 

React: Leaflet html Controls

This entry is part 4 of 9 in the series React: Leaflet

In this tutorial I will demonstrate how to add html controls to your leaflet map. Refer to the documentation for more information.

Before We Begin:

Really you can create any html control just substitute div for whatever you want. Below are just some basic examples.

Div

  1. var divContainer = L.DomUtil.create("div", "myClassName");

Image

  1. var img = L.DomUtil.create("img", "myClassName");

Label

  1. var label = L.DomUtil.create("label", "myClassName");

Span

  1. var span = L.DomUtil.create("span", "myClassName");

Input

  1. var input = L.DomUtil.create("input", "myClassName");

BR

  1. var br = L.DomUtil.create("br", "myClassName");

You can modify the html control with additional values such as

  1. #style
  2. divContainer.style.display = "";
  3.  
  4. #id
  5. divContainer.id = "myId";
  6.  
  7. #name
  8. divContainer.name = "myId";
  9.  
  10. #img src
  11. divContainer.src = "";
  12.  
  13. #title
  14. divContainer.title = "";
  15.  
  16. #innerHTML
  17. divContainer.innerHTML = "";
  18.  
  19. #type
  20. divContainer.type= "checkbox";
  21.  
  22. #checked
  23. divContainer.checked= false;
  24.  
  25.  

Parent Control

You can add the control to a parent control in the following way.

  1. var divContainer = L.DomUtil.create("div", "myClassName");
  2.  
  3. var subContainer = L.DomUtil.create("div", "myClassName", divContainer);

React: Leaflet EasyButton

This entry is part 3 of 9 in the series React: Leaflet

In this tutorial I will demonstrate how to add a easy button to your leaflet map. This will just be a basic example. For more information refer to the documentation.

Before We Begin:

Node Package Install:

  1. npm install leaflet-easybutton --save

Edit app/home/leaflet/js/map.jsx:

  1. //Add the leaflet easybutton package
  2. require("leaflet-easybutton");
  3. require("leaflet-easybutton/src/easy-button.css");
  4.  
  5. //Somehwere on your page add the following.
  6.  
  7.  
  8. //Check out https://github.com/CliffCloud/Leaflet.EasyButton for more uses
  9. L.easyButton("<div id="tag" class="glyphicon glyphicon-tag" />", function(btn, map) {
  10. map.setView([42.3748204,-71.1161913],16);
  11. }, { position: "topleft"}).addTo(this.map);
  12.  

React: Leaflet Modal

This entry is part 2 of 9 in the series React: Leaflet

In this tutorial I will demonstrate how to add a modal dialog to your leaflet map. Refer to the documentation for more information.

Before We Begin:

Node Package Install:

  1. npm install leaflet-modal --save

Edit app/home/leaflet/js/map.jsx:

  1. //Add the leaflet modal package
  2. require("leaflet-modal");
  3. require("leaflet-modal/dist/leaflet.modal.min.css");
  4.  
  5. //Somewhere on your page add the following. You can even put it on a onclick event or whatever
  6.  
  7. //Create a test control for your modal control.
  8. this.modalContainer = L.DomUtil.create("div");
  9. map.openModal({
  10. zIndex: 10000,
  11. element: this.modalContainer, //The container to display in the modal
  12. OVERLAY_CLS: "overlay", //This is a built in class which you can change if you want
  13. MODAL_CLS: "modal", //This is a built in class which you can change if you want
  14. height: 200, width: 200,
  15. MODAL_CONTENT_CLS: "modal-content", //This is a built in class which you can change if you want
  16. CLOSE_CLS: "modal-close-hide" //The property for close class
  17. });

Edit app/home/leaflet/css/map.css:

  1. .modal-close-hide {
  2. /*Class for hiding the modal*/
  3. display: none;
  4. }

React: Basic Leaflet Map Example

This entry is part 1 of 9 in the series React: Leaflet

In this tutorial I will walk you through incorporating leaflet map in your application. This is just a basic setup walkthrough. We do not deal with overlays or extending controls.

Documentation:

Leaflet
Leaflet Providers

Before We Begin:

If you have not done so already refer to how to Build a React/Python Site to get your basic site up and running.

Node Package Installs:

  1. npm install leaflet-providers --save
  2. npm install leaflet --save

Create Needed Folders/Files:

  • app
    • folder: leaflet
      • folder: css
        • file: map.css
      • folder: js
        • file: map.jsx

Webpack:

Add the following loader for handling images to your webpack.config.js file.

  1. { test: /.*\.(gif|png|jpe?g|svg)$/i, loader: "file-loader?hash=sha512&digest=hex&name=[name].[ext]" }

Edit app/leaflet/js/map.jsx:

We are going to create the map control. Refer to comments below for explanations.

  1. window.jQuery = window.$ = require("jquery");
  2. //React packages
  3. var React = require("react");
  4. var createReactClass = require("create-react-class");
  5.  
  6. //Leaflet packages
  7. import L from "leaflet";
  8. import "leaflet/dist/leaflet.css";
  9.  
  10. //LeafLet providers
  11. require("leaflet-providers");
  12.  
  13. //map css you will create
  14. import "../css/map.css";
  15.  
  16. var LeafLetMap = createReactClass({
  17. getInitialState: function() {
  18. return {};
  19. },
  20. displayMap: function() {
  21. //Setup/initialize the map control
  22. window.map = this.map = L.map("map", {
  23. attributionControl: false, //http://leafletjs.com/reference-1.2.0.html#control-attribution
  24. }).setView([0,0], 1);
  25. //A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft)
  26. L.control.scale({ //http://leafletjs.com/reference-1.2.0.html#control-scale
  27. metric: false,
  28. imperial: true
  29. }).addTo(this.map);
  30. //You can check out all the free providers here https://github.com/leaflet-extras/leaflet-providers
  31. //Below are just examples
  32. this.layers = {
  33. OpenMapSurferRoads: L.tileLayer.provider('OpenMapSurfer.Roads'),
  34. HyddaFull: L.tileLayer.provider('Hydda.Full'),
  35. StamenTerrain: L.tileLayer.provider('Stamen.Terrain'),
  36. EsriWorldStreetMap: L.tileLayer.provider('Esri.WorldStreetMap'),
  37. EsriWorldTopoMap: L.tileLayer.provider('Esri.WorldTopoMap'),
  38. EsriWorldTerrain: L.tileLayer.provider('Esri.WorldTerrain'),
  39. OpenTopoMap: L.tileLayer.provider('OpenTopoMap'),
  40. OpenStreetMapBlackAndWhite: L.tileLayer.provider('OpenStreetMap.BlackAndWhite'),
  41. OpenStreetMapHOT: L.tileLayer.provider('OpenStreetMap.HOT')
  42. };
  43.  
  44. //Add the default layer you want to use
  45. this.layers.OpenMapSurferRoads.addTo(this.map);
  46.  
  47. //Add the layer control to the top left corner
  48. this.layerControl = L.control.layers(this.layers, {}, { position: "topleft" }).addTo(map);
  49. },
  50. componentDidMount: function() {
  51. //Done after mounting so that it sees the div you are going to map to
  52. this.displayMap();
  53. },
  54. render: function() {
  55. return (
  56. <div className="div-flex">
  57. <div id="map" key="map" className="map"></div>
  58. </div>
  59. );
  60. }
  61. });
  62.  
  63. module.exports = { LeafLetMap:LeafLetMap };

Edit app/leaflet/css/map.css:

  1. .map {
  2. /*Changes the width and height of the map*/
  3. height: 400px;
  4. width: 800px;
  5. }
  6.  
  7. div.leaflet-top {
  8. /*OPTIONAL: This is only needed if your controls start going behind the map.*/
  9. z-index: 1001;
  10. }
  11.  
  12. .leaflet-control-layers-toggle {
  13. /*Changes the width and height of the layer control*/
  14. height: 30px !important;
  15. width: 30px !important;
  16. }

Edit app/home/js/home.jsx:

  1. //Import your leaflet map control from the page you created above
  2. import { LeafLetMap } from "../../leaflet/js/map.jsx";
  3.  
  4. //In the render function add your control
  5. render: function() {
  6. return (
  7. <div className="div-flex">
  8. <LeafLetMap ref="map" />
  9. </div>
  10. );
  11. }

 

 

 

Python: Flask Resource

This tutorial helps setup flask restful api’s.

Install Python Packages:

Open cmd and navigate into your testApp folder and run the following commands.

  1. pip install flask-RESTful && pip freeze > requirements.txt
__init__.py:

On the init of your application you will need to setup flask_restful. There are config options you could set for config.py. Look into it!

  1. from flask_restful import Api
  2. api = Api(app)
  3.  
  4. #Add api endpoints
  5. #Get
  6. api.add_resource(home.views.MyResource, '/home/getMyData/')
  7.  
  8. #Post
  9. api.add_resource(home.views.MyResource, '/home/getMyData/', methods=['POST'])
Setup home views.py:

You need to import Resource in it’s most simplistic form. However if you want to deal with request parameters add in reqparse and inputs. Inputs give you access to boolean that way a boolean can be parsed into a python boolean easily.

  1. from flask_restful import Resource, reqparse, inputs

You can now use get, post, etc. I will give you three examples below.

Get:

  1. class MyResource(Resource):
  2. def get(self):
  3. return {}

Get /w Parameter:

  1. class MyResource(Resource):
  2. def get(self, var):
  3. return {}

Get /w Parameter & Request Parameter:

  1. class MyResource(Resource):
  2. def get(self, var):
  3. parser = reqparse.RequestParser()
  4. parser.add_argument('new_request_var', type=str, default='')
  5.  
  6. #If you want to have a boolean request parameter do the following.
  7. parser.add_argument('new_request_var_bool', type=inputs.boolean, default=False)
  8.  
  9. args = parser.parse_args(strict=True)
  10. new_request_var = args['new_request_var']
  11. new_request_var_bool = args['new_request_var_bool']
  12.  
  13. return {}

Post:

  1. class MyResource(Resource):
  2. def post(self):
  3. return {}

React Add CSS to Your Site

If you haven’t already done so please follow this tutorial in setting up your React/Python site.

Folder Structure:
  • You need to add file(s) to your existing structure.
  • Inside testApp create the following:
    • folder: app
      • folder: home
      • folder: css
        • file: home.css
NPM:

We need to add style-loader and css-loader to our application.

  1. npm install style-loader --save
  2. npm install css-loader --save
  3. npm install create-react-class --save
Webpack.config.js Setup:

Now that we have installed our loaders we need to setup webpack.config.js to use our new loaders. The below will go in the “loaders” array.

  1. {
  2. test: /\.css$/,
  3. loader: 'style-loader!css-loader'
  4. }

Things to note:

  • The ! in the loader section just means it applies to both.
  • The .css in the test area says any css file.
Home.jsx Modification:

We need to pull in our css file for home.jsx. Notice the “require” now in our home.jsx file and that we added a class to our div.

  1. var React = require("react");
  2. var ReactDOM = require("react-dom");
  3. var createReactClass = require("create-react-class");
  4.  
  5. require("../css/home.css");
  6.  
  7. var Home = createReactClass({
  8. render: function() {
  9. return (<div className="div-hi">Hi</div>);
  10. }
  11. });
  12.  
  13. ReactDOM.render(<Home />, document.getElementById("app"));
Home.css Setup:

Put anything you want in the css file as long as it matches the classname we set in home.jsx.

  1. .div-hi {
  2. color: red;
  3. }
Run:

We can now run the following to build and deploy our site. It will be available on http://localhost:5000/. Once you login you will be able to see our red “hi”. As long as you following the building a react python site creation.

  1. webpack
  2. flask run

Flask: React Website

This whole tutorial describes in depth how to create a React website with Python. You must have Eclipse installed before you continue. If you have it already installed and configured you can continue on. Note that you should probably have HTML Editor and TypeScript IDE installed for Eclipse.

FYI: I am using Windows at the moment for this tutorial but you can substitute Ubuntu in if you so chose.

We will require Postgres 9.4, nodejs before you continue. You can get Nodejs from here. You can get Postgres 9.4 from here.

In this tutorial we use Flask. If you are not familiar with it go here. Flask is a lightweight Python web framework based on Werkzeug and Jinja 2.

Folder Structure:
  • You will need to create a folder called “testApp”.
  • Inside testApp create the following:
    • folder: app
      • file: models.py
      • file: __init__.py
      • folder: auth
        • file: __init__.py
        • file: views.py
      • folder: home
        • file: __init__.py
        • file: views.py
        • folder: js
          • file: home.jsx
      • folder: templates
        • file: base.html
        • file: login.html
        • file: register.html
    • file: config.py
    • file: requirements.txt
    • file: webpack.config.js
    • file: run.py
    • folder: instance
      • file: config.py
    • folder: static
      • folder: common
        • folder: css
          • file: base.css
      • file: manifest.json
    • .babelrc
Install Python Packages:

Open cmd/terminal and navigate into your testApp folder and run the following commands.

  1. pip install flask-sqlalchemy && pip freeze > requirements.txt
  2. pip install flask-login && pip freeze > requirements.txt
  3. pip install flask-migrate && pip freeze > requirements.txt
  4. pip install psycopg2 && pip freeze > requirements.txt
  5. pip install flask-Webpack && pip freeze > requirements.txt
  6. pip install Flask-WTF && pip freeze > requirements.txt
  7. pip install flask-bootstrap && pip freeze > requirements.txt

Couple things to note:

  • The “&& pip freeze > requirements.txt” saves the install in requirements.txt.
  • flask-migrate: database migrations package
  • flask-sqlalchemy: model engine for your database.
  • flask-login: provides user session management for Flask
  • psycopg2: Postgres driver
  • flask-Webpack: A Flask extension to manage assets with Webpack
  • flask-WTF: flask form validation
  • flask-bootstrap: An extension that includes Bootstrap in your project, without any boilerplate code
Routing:

For the purpose of this example we are using the basic Flask implementation. IE: @home.route(‘/’). However if you want to do a more advanced routing do Resource.

Database:

Open PgAdmin III and create yourself a database called “testApp”. Also create a user with password granting access to testApp database. Permission as you see fit. Don’t forget to write down your password :).

Setup Config.py:

Read here for SqlAlchemy configruation options. DEBUG is for flask debugging.

  1. class Config(object):
  2. """
  3. This is the shared common configurations
  4. """
  5.  
  6. # Put any configurations here that are common across all environments
  7.  
  8. class DevelopmentConfig(Config):
  9. """
  10. This is the development configurations
  11. """
  12. DEBUG = True
  13. SQLALCHEMY_ECHO = True #Display queries to console
  14.  
  15. class ProductionConfig(Config):
  16. """
  17. This is the production configurations
  18. """
  19. DEBUG = False
  20. SQLALCHEMY_ECHO = False #Do not Display queries to console
  21.  
  22. app_config = {
  23. 'development': DevelopmentConfig,
  24. 'production': ProductionConfig
  25. }

Things to Note:

Notice how we don’t have any database connections in this config.py. That is because we really shouldn’t checkin to source control our database connection strings, etc.

Setup instance config.py:

We open the file config.py inside our “instance” folder and add this line only.

  1. SQLALCHEMY_DATABASE_URI = "postgresql://##USER##:##PASSWORD##@##HOST##/testApp"
Setup __init__.py in “app” folder:
  1. from flask import Flask
  2. from flask_sqlalchemy import SQLAlchemy
  3. from flask_login import LoginManager
  4. from flask_migrate import Migrate
  5. from flask_bootstrap import Bootstrap
  6. import os
  7.  
  8. #Importing from the config.py
  9. from config import app_config
  10.  
  11. # db variable initialization
  12. db = SQLAlchemy()
  13.  
  14. #The flask login manager
  15. login_manager = LoginManager()
  16.  
  17. webpack = Webpack()
  18.  
  19. def create_app(config_name):
  20. #This will be either "development" or "production" mapped to what we write in the config.py application
  21. #static_folder is where the static folder will be located
  22. app = Flask(__name__, instance_relative_config=True, static_folder=os.path.join(os.getcwd(), "static"))
  23. print('Running in %s' % (config_name))
  24. app.config.from_object(app_config[config_name])
  25. app.config.from_pyfile('config.py')
  26. #You need a secret key to be able to utilise the database connection
  27. app.secret_key = 'Awesome App'
  28. Bootstrap(app)
  29. db.init_app(app)
  30. #This will make it so our chunked js files are able to be loaded on the template
  31. app.config.update({'WEBPACK_MANIFEST_PATH': '../manifest.json'})
  32. webpack.init_app(app)
  33.  
  34. #if a user tries to access a page that they are not authorized to, it will redirect to the specified view and display the specified message.
  35. login_manager.init_app(app)
  36. login_manager.login_message = "You must be logged in to access this page."
  37. #auth.login is not the route but actually the class path.
  38. login_manager.login_view = "auth.login"
  39. #This let's us do our migrations
  40. migrate = Migrate(app, db)
  41.  
  42. #Bring in our new tables
  43. from app import models
  44.  
  45. #Our blueprints for our app
  46.  
  47. #This is how you get authenticated
  48. from .auth import auth as auth_blueprint
  49. app.register_blueprint(auth_blueprint)
  50. #Bring in the home module
  51. from .home import home as home_blueprint
  52. app.register_blueprint(home_blueprint)
  53.  
  54. return app
Environment Variable Setup:

Flask has two environment variables that you can set which point to the environment to use and the run.py file. These are FLASK_CONFIG and FLASK_APP. I set my environment to “development” and the app to use “run.py”. Notice that “development” maps to the key value pair in config.py.

Setup run.py:

Notice how we utilise the FLASK_CONFIG from the environment variables to setup our environment and grab the right config class.

  1. import os #We need this to get the OS ENV VARIABLE 'FLASK_CONFIG'
  2.  
  3. #You are going to import the create_app from the __init__.py file
  4. from app import create_app
  5.  
  6. #In our environment variables we create "FLASK_CONFIG" and set our value either development or production
  7. config_name = os.getenv('FLASK_CONFIG')
  8. app = create_app(config_name)
  9.  
  10. if __name__ == '__main__':
  11. app.run()

Now the fun really starts!!!

Setup models.py:

We setup our User model ensuring security of our password. Later on I will show you what happens with flask-migrate.

  1. from flask_login import UserMixin
  2. from werkzeug.security import generate_password_hash, check_password_hash
  3.  
  4. from app import db
  5.  
  6. class User(UserMixin, db.Model):
  7. """
  8. Create an Users table
  9. """
  10.  
  11. # Ensures table will be named in plural and not in singular
  12. # as is the name of the model
  13. __tablename__ = 'users'
  14.  
  15. id = db.Column(db.Integer, primary_key=True)
  16. email = db.Column(db.String(60), index=True, unique=True)
  17. username = db.Column(db.String(60), index=True, unique=True)
  18. first_name = db.Column(db.String(60), index=True)
  19. last_name = db.Column(db.String(60), index=True)
  20. password_hash = db.Column(db.String(128))
  21.  
  22. @property
  23. def password(self):
  24. """
  25. Prevent pasword from being accessed
  26. """
  27. raise AttributeError('password is not a readable attribute.')
  28.  
  29. @password.setter
  30. def password(self, password):
  31. """
  32. Set password to a hashed password
  33. """
  34. self.password_hash = generate_password_hash(password)
  35.  
  36. def verify_password(self, password):
  37. """
  38. Check if hashed password matches actual password
  39. """
  40. return check_password_hash(self.password_hash, password)
  41.  
  42. def __repr__(self):
  43. return ''.format(self.username)
Generate User Table:

Using flask-migrate we can now auto generate our User table into Postgres testApp database.

  1. Run “flask db init” to create our migration repository
    1. A “migrations” folder is created automatically.
  2. Run “flask db migrate”
    1. This generates the migration script
  3. Run “flask db upgrade”
    1. This creates the missing migrations into the database. AKA the users table.
    2. You will notice another table also got created “alembic_version”. This is how it stores the version it is at.
  4. Confirm that the db was migrated successfully.
Create Our Templates:

We use the base.html file for our react pages using the “app” id on the div. The login.html is for our login form and register.html is to register a new user. You can use the base.css file in the static/common/css folder to style it how you want. I recommend using flex.

base.html:

  1. <!DOCTYPE html>
  2. {% import "bootstrap/utils.html" as utils %}
  3. {% import "bootstrap/wtf.html" as wtf %}
  4. {% extends "bootstrap/base.html" %}
  5. <html>
  6. <head>
  7. {% block head %}
  8. {{ super() }}
  9. <title>{{title}}</title>
  10. <link rel="stylesheet" type="text/css" href={{ url_for("static", filename="common/css/base.css") }} />
  11. {% endblock %}
  12. </head>
  13. {% block content %}
  14. <div class="container-app">
  15. <div class="container-header">Team Link</div>
  16. <div class="container-body" id="app"></div>
  17. <script type="text/javascript" src={{ asset_url_for(script_name) }}></script>
  18. </div>
  19. {% endblock %}
  20. </html>

login.html:

  1. <!DOCTYPE html>
  2. {% import "bootstrap/utils.html" as utils %}
  3. {% import "bootstrap/wtf.html" as wtf %}
  4. {% extends "bootstrap/base.html" %}
  5. <html>
  6. <head>
  7. {% block head %}
  8. {{ super() }}
  9. <title>{{title}}</title>
  10. <link rel="stylesheet" type="text/css" href={{ url_for("static", filename="common/css/base.css") }} />
  11. {% endblock %}
  12. </head>
  13. {% block content %}
  14. <div class="container-app">
  15. <div class="container-header">My Awesome App</div>
  16. <div class="container-body" id="app">
  17. <div class="panel panel-default">
  18. <div class="panel-heading">
  19. <h3 class="panel-title">Login</h3>
  20. </div>
  21. <div class="panel-body">
  22. {{ wtf.quick_form(form) }}
  23. </div>
  24. {{ utils.flashed_messages() }}
  25. Click here to <a href="/register">register</a>
  26. </div>
  27. </div>
  28. </div>
  29. {% endblock %}
  30. </html>

register.html

  1. <!DOCTYPE html>
  2. {% import "bootstrap/utils.html" as utils %}
  3. {% import "bootstrap/wtf.html" as wtf %}
  4. {% extends "bootstrap/base.html" %}
  5. <html>
  6. <head>
  7. {% block head %}
  8. {{ super() }}
  9. <title>{{title}}</title>
  10. <link rel="stylesheet" type="text/css" href={{ url_for("static", filename="common/css/base.css") }} />
  11. {% endblock %}
  12. </head>
  13. {% block content %}
  14. <div class="container-app">
  15. <div class="container-header">Team Link</div>
  16. <div class="container-body" id="app">
  17. <div class="panel panel-default">
  18. <div class="panel-heading">
  19. <h3 class="panel-title">Register</h3>
  20. </div>
  21. <div class="panel-body">
  22. {{ wtf.quick_form(form) }}
  23. </div>
  24. {{ utils.flashed_messages() }}
  25. Click here to <a href="login">login</a>
  26. </div>
  27. </div>
  28. </div>
  29. {% endblock %}
  30. </html>
Setup home __init__.py:

This creates the blueprint that we have in app.__init__.py.

  1. from flask import Blueprint
  2.  
  3. home = Blueprint('home', __name__)
  4.  
  5. #This is the views.py from the home directory.
  6. from . import views
Setup home views.py:

@login_required let’s flask know that you need to be logged in to get to this page. Don’t forget to see “render_template” method. How it has “script_name” in it and it uses base.html template. “script_name” was utilised in base.html. It brings in our js file for us on each page we go to.

  1. from flask import render_template
  2. from flask_login import login_required
  3.  
  4. #This is our blueprint we setup in __init__.py
  5. from . import home
  6.  
  7. @home.route('/')
  8. @login_required
  9. def homepage():
  10. """
  11. Render the homepage template on the / route
  12. """
  13. return render_template('base.html', script_name='home.js', title="Welcome")
Setup React home JSX file:

React uses jsx files. So in my home directory I have a js folder and inside that we have our home.jsx file. Let’s set that up to something really basic. Remember above I said in the “render_template” we use the div id “app”. The ReactDOM will put our class in that spot. I will show you later how that is done.

  1. var React = require("react");
  2. var ReactDOM = require("react-dom");
  3. var createReactClass = require("create-react-class");
  4.  
  5. var Home = createReactClass({
  6. render: function() {
  7. return (<div>Hi</div>);
  8. }
  9. });
  10.  
  11. ReactDOM.render(<Home />, document.getElementById("app"));
Node Init:

We need to go to our root directory testApp from command prompt and run the following in the exact order.

  1. npm init
  2. npm install react react-dom --save
  3. npm install webpack webpack-dev-server --save
  4. npm install --save-dev babel babel-core babel-loader babel-preset-es2015 babel-preset-react
  5. npm install create-react-class --save
  6. npm install bootstrap --save
  7. npm install jquery --save
  8. npm install clean-webpack-plugin --save-dev
  9. npm install manifest-revision-webpack-plugin --save-dev
  10. npm install sync-exec --save-dev
  11. npm install uglifyjs-webpack-plugin --save-dev

Things to Note:

  • npm init: Creates package.json file
  • npm install –save: will save the install to package.json
  • Each package install went into a new directory called “node_modules”.
Setup webpack.config.js:

We want to transition our jsx files to .js. Remember back in app.__init__.py we setup the static folder location. Checkout the “path” key below and now we know how it knows where it’s assets are going to be located. Our entry key value pair is the locations of each of our jsx files to create assets from. Then we have our loaders.

  1. var path = require("path");
  2. var webpack = require('webpack');
  3. var ManifestRevisionPlugin = require('manifest-revision-webpack-plugin');
  4. const CleanWebpackPlugin = require('clean-webpack-plugin');
  5.  
  6. module.exports = {
  7. entry: {
  8. "home": [path.resolve(__dirname, "./app/home/js/home.jsx")],
  9. },
  10. output: {
  11. path: path.join(__dirname, "static"),
  12. publicPath: "/static/",
  13. filename: "[name]-[hash].js"
  14. },
  15. plugins: [
  16. new CleanWebpackPlugin(["static/*.js", "static/manifest.json"], {root: __dirname, verbose: true, dry: false, exclude: ["base.css"]}),
  17. new ManifestRevisionPlugin(path.resolve(__dirname, "./manifest.json"), {rootAssetPath: './static', ignorePaths: ['./node_modules']}),
  18. new webpack.NoEmitOnErrorsPlugin(),
  19. new UglifyJsPlugin(),
  20. new webpack.optimize.AggressiveMergingPlugin(),
  21. new webpack.HotModuleReplacementPlugin()
  22. ],
  23. module: {
  24. loaders: [
  25. {
  26. test: /\.jsx?$/,
  27. exclude: /(node_modules)/,
  28. loader: 'babel-loader',
  29. query: {
  30. presets: ['react','es2015']
  31. }
  32. }
  33. ]
  34. }
  35. };
.babelrc

Set the following in your file at the root directory.

  1. {
  2. "presets": [ "es2015", "react" ]
  3. }
Let’s Test Node & Webpack:

Open command prompt and navigate to our testApp folder and run “webpack”. You will notice that a “static” folder is created in our root directory. In it we will now see “home.js” file. Remember back above we set __init__.py static folder and in home.views.py file we said in render_template script_name “home.js”. This is how it all maps together.

Setup auth __init__.py:

This creates the blueprint that we have in app.__init__.py.

  1. from flask import Blueprint
  2.  
  3. auth = Blueprint('auth', __name__)
  4.  
  5. #This is the views.py from the auth directory.
  6. from . import views

Setup auth views.py:

  1. from flask import flash, redirect, render_template, url_for
  2. from flask_login import login_required, login_user, logout_user
  3. from flask_wtf import FlaskForm
  4. from wtforms import PasswordField, StringField, SubmitField, ValidationError
  5. from wtforms.validators import DataRequired, Email, EqualTo
  6. from .. import db, login_manager
  7. from ..models import User
  8.  
  9. from . import auth
  10.  
  11. class RegistrationForm(FlaskForm):
  12. """
  13. Form for users to create new account
  14. """
  15. email = StringField('Email', validators=[DataRequired(), Email()])
  16. username = StringField('Username', validators=[DataRequired()])
  17. first_name = StringField('First Name', validators=[DataRequired()])
  18. last_name = StringField('Last Name', validators=[DataRequired()])
  19. password = PasswordField('Password', validators=[
  20. DataRequired(),
  21. EqualTo('confirm_password')
  22. ])
  23. confirm_password = PasswordField('Confirm Password')
  24. submit = SubmitField('Register')
  25.  
  26. def validate_email(self, field):
  27. if User.query.filter_by(email=field.data).first():
  28. raise ValidationError('Email is already in use.')
  29.  
  30. def validate_username(self, field):
  31. if User.query.filter_by(username=field.data).first():
  32. raise ValidationError('Username is already in use.')
  33.  
  34. class LoginForm(FlaskForm):
  35. """
  36. Form for users to login
  37. """
  38. email = StringField('Email', validators=[DataRequired(), Email()])
  39. password = PasswordField('Password', validators=[DataRequired()])
  40. submit = SubmitField('Login')
  41.  
  42. @login_manager.user_loader
  43. def load_user(id):
  44. #This is the how we locate the user in our testApp database
  45. return User.query.get(int(id))
  46.  
  47. @auth.route('/register', methods=['GET', 'POST'])
  48. def register():
  49. form = RegistrationForm()
  50. if form.validate_on_submit():
  51. user = User(email=form.email.data,
  52. username=form.username.data,
  53. first_name=form.first_name.data,
  54. last_name=form.last_name.data,
  55. password=form.password.data)
  56.  
  57. # add user to the database
  58. db.session.add(user)
  59. db.session.commit()
  60. flash('You have successfully registered! You may now login.')
  61.  
  62. # redirect to the login page
  63. return redirect(url_for('auth.login'))
  64.  
  65. # load registration template
  66. return render_template('register.html', form=form, title='Register')
  67.  
  68. @auth.route('/login', methods=['GET', 'POST'])
  69. def login():
  70. form = LoginForm()
  71. if form.validate_on_submit():
  72. # check whether user exists in the database and whether
  73. # the password entered matches the password in the database
  74. user = User.query.filter_by(email=form.email.data).first()
  75. if user is not None and user.verify_password(
  76. form.password.data):
  77. # log user in
  78. login_user(user)
  79.  
  80. # redirect to the dashboard page after login
  81. return redirect("/")
  82.  
  83. # when login details are incorrect
  84. else:
  85. flash('Invalid email or password.')
  86.  
  87. # load login template
  88. return render_template('login.html', form=form, title='Login')
  89.  
  90. @auth.route('/logout')
  91. @login_required
  92. def logout():
  93. """
  94. Handle requests to the /logout route
  95. Log an user out through the logout link
  96. """
  97. logout_user()
  98. flash('You have successfully been logged out.')
  99.  
  100. # redirect to the login page
  101. return redirect(url_for('auth.login'))
Let’s Run our App:

Open command prompt navigate to our testApp folder and run “flask run”. If no mistakes were made you should now be able to navigate to our site. http://localhost:5000.

 

Resources:

In learning how to incorporate flask into python I used the following part one only tutorial as a guide. Very helpful.

HighCharts: Basic Graphing

This entry is part 1 of 2 in the series React: Highcharts

HighCharts is a pretty cool graphing package. Below is an example of how you can create an universal React class for a HighCharts graph.

You will need to install the package. At the time of this writing I am using 5.0.6.

You will also need to import HighCharts and require the charts.

  1. import Highcharts from "highcharts/highcharts.js";
  2. window.Highcharts = Highcharts;
  3. require("highcharts/highcharts-more.js")(Highcharts);

In the state I hold these values to manage how the chart loads and displays data.

  1. getInitialState: function() {
  2. return {
  3. chartSettings: null, //Holds the chart settings data
  4. loaded: false, //Determines if the chart has been loaded
  5. chart: null, //The chart
  6. data: [], //The data to utilize for the chart. It's most likely in series format
  7. };
  8. },

In the component methods check to see when the class has been loaded with data or reset if needed.

  1. componentDidUpdate: function() {
  2. if (!this.state.loaded) { //The chart hasn't been loaded with data so load it and refresh the chart
  3. this.setState({
  4. loaded: true,
  5. data: this.props.data
  6. }, () => { this.chart(); });
  7. }
  8. },
  9. componentWillReceiveProps: function(newprops) {
  10. if (this.state.loaded && this.props != newprops) { //The chart has been loaded but the data has changed. Refresh the chart after
  11. this.setState({
  12. data: newprops.data
  13. }, () => { this.chart(); });
  14. }
  15. },

The class the render method is how the chart assigns to the UI.

  1. render: function() {
  2. return (<div id={this.props.id}></div>
  3. ); },

You can create a “chart” method. Which you can use to manage the display of the chart. The main section of it is how to display the chart after you have modified the chart settings. You could also utilize a props for controlling whether to show the loading or not. Totally up to you.

  1. this.setState({
  2. loaded: true, //The data and chart has been loaded
  3. chart: new Highcharts.Chart(chartSettings) //Set the chart
  4. }, () => {
  5. if (!this.props.data.length == 0) { //If no data is present yet then show a loading image
  6. this.state.chart.showLoading();
  7. this.state.chart.redraw();
  8. } else { //The data has been loaded.
  9. this.state.chart.hideLoading();
  10. this.state.chart.redraw();
  11. }
  12. });

In the “chart” method you should clean up your existing chart before generating a new one.

  1. if (this.state.chart !== null) {
  2. this.state.chart.destroy();
  3. this.state.chart = null;
  4. }

There are so many ways of controlling the chartsettings. I will try to cover a vast majority of the options. The basic definition looks like this.

  1. chartSettings = $.extend(true, {},
  2. this.props.chartSettings,
  3. {
  4. chart: {
  5. renderTo: this.props.id, //The id you passed into the class
  6. backgroundColor: "",
  7. type: this.props.chart_type, //By passing in the chart type it will be open to various types of charts.
  8. height: 500, //You can specify the height of the graph if you want.
  9. zoomType: "xy", //If you want to be able to zoom.
  10. },
  11. credits: {
  12. enabled: false //Turns off the powered by
  13. },
  14. title: {
  15. text: this.props.title,
  16. style: { color: "white" }
  17. },
  18. subtitle: {
  19. text: this.props.sub_title
  20. },
  21. tooltip: {
  22. },
  23. plotOptions: {
  24. },
  25. series: thisInstance.state.data
  26. });

Tooltip has various options. One I like to use is the “formatter” functionality. This will allow you to modify what is displayed on hover.

  1. tooltip: {
  2. formatter: function(){
  3. var pointIndex = this.point.index;
  4. var seriesName = this.point.series.name;
  5. }
  6. }

There is also xAxis option. You can do a variety of different things. Depending on how you create your graph determines what options you should use. The type in xAxis can have a few different options. I show you “datetime” below. But you can also choose “linear” which is numerical data as well as “category” which allows you to put string data on the X axis.

  1. xAxis: {
  2. type: "datetime",
  3. categories: this.props.categories,
  4. title: {
  5. enabled: true,
  6. },
  7. showLastLabel: true,
  8. showFirstLabel: true,
  9. tickInterval: 15, //I chose to increment to x value by 15 days. But you can choose whatever you want
  10. labels: {
  11. formatter: function () {
  12. if (the type is a date == "date") {
  13. return Highcharts.dateFormat("%m/%d", this.value); //You can format however you like
  14. } else {
  15. return this.value;
  16. }
  17. }
  18. }
  19. },

There is also yAxis option. You can do a variety of different things. Depending on how you create your graph determines what options you should use. Here is an example.

  1. yAxis: {
  2. allowDecimals: true,
  3. title: {
  4. align: "high"
  5. },
  6. labels: {
  7. overflow: "justify",
  8. formatter: function() {
  9. return this.value;
  10. }
  11. },
  12. },

You can add onClick events to series points if you want.

  1. plotOptions: {
  2. series: {
  3. point: {
  4. events: {
  5. click: function(e){
  6. }
  7. }
  8. }
  9. }
  10. }

There are various graph types. For example “pie”, “bar”, “scatter”, etc. Here are a few different examples of a basic setup.

  1. plotOptions: {
  2. pie: {
  3. allowPointSelect: true, //When you click the pie slice it moves out slightly
  4. cursor: "pointer",
  5. shadow: false,
  6. dataLabels: {
  7. enabled: true,
  8. formatter:function(){
  9. },
  10. color: "white",
  11. style: {
  12. textShadow: false
  13. }
  14. }
  15. },
  16. bar: {
  17. dataLabels: {
  18. enabled: true,
  19. allowOverlap: true, //Labels will overlap. Turns this off if you don't want your labels to overlap.
  20. }
  21. },
  22. scatter: {
  23. dataLabels: {
  24. crop: false, //Labels will not be hidden
  25. },
  26. marker: {
  27. radius: 3,
  28. states: {
  29. hover: {
  30. enabled: true
  31. }
  32. }
  33. },
  34. states: {
  35. hover: {
  36. marker: {
  37. enabled: false
  38. }
  39. }
  40. }
  41. }
  42. }

Highcharts: Add Custom Buttons

This entry is part 2 of 2 in the series React: Highcharts

If you’ve never used HighCharts for your graphing needs I highly suggest it. Very customizable and easy to use.

You will need to require the exporting requirements.

  1. import Highcharts from "highcharts/highcharts.js";
  2. window.Highcharts = Highcharts;
  3. require("highcharts/modules/exporting")(Highcharts);

If you would like to add a custom button to your graph you can use the exporting section like below.

  1. exporting: {
  2. buttons: {
  3. customButton: {
  4. text: "Button Text",
  5. onclick: function () {
  6. }
  7. },
  8. },
  9. }

React: Export Module

Sometimes we need exportable modules for use through our applications. It is pretty straight forward to export a module.

NPM Installs:

  1. npm install create-react-class --save
  2. npm install prop-types --save
  3. npm install react --save
  4. npm install react-dom --save

Export:

  1. module.exports = {exportedModuleName:ModuleName};

exportedModuleName is the name that you use in other pages.
ModuleName is the name of the module to export.

The module will look something like this.
This one is just a TD module. But really you can do anything you want.

  1. window.jQuery = window.$ = require("jquery");
  2. import React from "react";
  3. import ReactDOM from "react-dom";
  4. var createReactClass = require('create-react-class');
  5. var propTypes = require('prop-types');
  6.  
  7. var MyExportableModule = createReactClass({
  8.       render: function() {
  9.             return React.createElement("anyelement", {className: this.props.className, key: this.props.name}, this.props.fields);
  10.       }
  11. });
  12.  
  13. MyExportableModule.PropTypes = {
  14.       name: React.PropTypes.string.isRequired,
  15.       fields: React.PropTypes.array.isRequired,
  16.       className: React.PropTypes.string
  17. };

 

 

 

React: Page Layout

There are many aspects of React below is just a sample of how you could setup a ReactJs page. Look up what each section does.

Go here to review the React Life Cycle. It is important to review this and understand it so that you dont make mistakes during your development.

NPM Installs:

  1. npm install create-react-class --save
  2. npm install react --save
  3. npm install react-dom --save

Class Setup:

  1. window.jQuery = window.$ = require("jquery");
  2. import React from "react";
  3. import ReactDOM from "react-dom";
  4. import "../css/newpage.css";
  5. var createReactClass = require('create-react-class');
  6.  
  7. var NewPage = createReactClass ({
  8.       getData: function() {
  9.             var params = {};
  10.             
  11.             $.ajax({
  12.                   url: "/my_web/service_method/",
  13.                   dataType: "json",
  14.                   data: params,
  15.                   success: function(data) {
  16.                         this.setState({
  17.                               "data": data
  18.                         }, () => {
  19.                               //If you want to do something after you get the data loaded
  20.                         });
  21.                   }.bind(this),
  22.                   error: function(xhr, status, err) {
  23.                         console.err("Bad");
  24.                   }.bind(this)
  25.             });
  26.       },
  27.       getInitialState: function() {
  28.             return{
  29.                   "data": [],
  30.             };
  31.       },
  32. componentDidMount: function() {
  33. },
  34. componentWillMount: function() {
  35.       this.getData();
  36. },
  37.       render: function() {
  38.  
  39.             return (
  40.                   <div key="div">
  41.                   </div>
  42.             );
  43.       }
  44. });
  45.  
  46. ReactDOM.render(<NewPage/>, document.getElementById("app-container"));