Managing 'window' object in Isomorphic App with ReactJS and Flask Python - flask

I am developing an application with Flask Backend with ReactJS front.
ReactJS app has been developed and bundled with webpack.
Everything works fine with client side rendering which is bundled with webpack.
I am now trying to add server side rendering with python-react .
But problem is, I have to share some variables to my ReactJS app via Jinja2 template in base template index.html which has the reactjs root component node <div id='react-node'></div>.
I had to send my routes and config to my application via jinja2 template like below ,
//index.html
<!doctype html>
<html>
...
...
<script type='text/javascript'>
var STATIC_IMAGE_ROOT = "{{ url_for('static', filename='img/') }}";
var ROUTES = { ... };
...
</script>
</html>
All the above js variables are being set to global window object .
But when I am trying to render the component in python, it throws exception for window object ReactRenderingError: react: ReferenceError: window is not defined .
What is the best way to solve this issue ?

There is no window global when rendering on the server. You can create a fake window, first checking if the window exists:
if (typeof(window) == 'undefined'){
global.window = new Object();
}
Alternatively, you can use jsdom, or a similar library to create a fake DOM.

Just add the following to webpack config:
// By default, Webpack is set up to target the browser,
// not a Node environment. Try setting target in your config:
target: 'node',

Related

Can i render VueJS with Django?

I would like to add Vue to my Django project, but i'm having troubles understanding
some parts of it.
At the actual moment, my project already has a bunch of templates and views. Everything is rendered by the views, the only JS i'm using is for Jquery. The need to add Vue comes to improve my UI. I don't need Vue to be my frontend, i only want to add some Vue components to my templates here and there.
After making some research, i found about the Webpack + Vue approach. It's not the right approach for my project since it should be used for a project where the frontend is entirely built on Vue and is divided from the Django backend, so it is not the right way for me.
At this point, the only way to go would be to add it using the CDN on my django html template:
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.0"></script>
Would this approach be possible?
Yes, this is possible.
Just add the script inside your template:
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.0"></script>
And then you can initialize the Vue components inside other script tags. It is advisable to change interpolation brackets from {{ }} to [[ ]], to avoid conflict with Django templating engine.
<div id="example">
<p>[[ hello ]]</p>
</div>
<script>
new Vue({
el: '#example',
delimiters: ['[[', ']]'],
data: { hello: 'Hello World!' }
})
</script>

Can't get to add JS to front via $this->load->view

I'm developing a module for OpenCart 3.x and I'm trying to insert some JavaScript code into website's front via $this->load->view() method but cannot get it to work, as the JS code doesn't appear in the DOM.
Here's an excerpt of my code:
/catalog/controller/extension/module/mymodule.php
class ControllerExtensionModuleMyModule extends Controller {
public function index() {
$this->load->language('extension/module/mymodule');
$this->load->model('checkout/order');
$this->load->model('setting/setting');
$this->load->model('design/layout');
$this->load->model('catalog/category');
$this->load->model('catalog/manufacturer');
$this->load->model('catalog/product');
$this->load->model('catalog/information');
$data['js_output'] = "Some JS output";
return $this->load->view('extension/module/mymodule', $data);
}
}
catalog/view/theme/default/template/extension/module/mymodule.twig
<script type="text/javascript">
console.log('This is working!");
</script>
Am I missing something?
Add an external javascript file via controller like this:
$this->document->addScript('catalog/view/javascript/my-external-script.js');
But if it's a block of javascript code, you don't need to edit controller file, just add it to your view file (twig or tpl):
<script type="text/javascript">
console.log("This is working!");
</script>
Finally you may need to clear caches (vqmod, ocmod, twig etc ...).
EDIT
If you want to prepare your javascript code in the controller, follow this:
controller
$data['js_output'] =
'<script type="text/javascript">
console.log("This is working!");
</script>';
Twig
{{ js_output }}
I have finally fixed the issue. It was a problem with the install() method not correctly inserting and loading the design/layout ($this->model_design_layout->getLayouts()).
If your module needs to insert a layout into the layout_module table, make sure you have the correct layout_id, code(which must be your module name), position (i.e: 'content_bottom') and sort_order(which often times is > 90).

ember-bootstrap: Navbar component repeats itself 12 times

I am using ember-bootstrap's Navbar example code in a simple Ember test app:
{{#bs-navbar as |navbar|}}
<div class="navbar-header">
{{navbar.toggle}}
<a class="navbar-brand" href="#">Brand</a>
</div>
{{#navbar.content}}
{{#navbar.nav as |nav|}}
{{#nav.item}}
{{#nav.link-to "home"}}Home{{/nav.link-to}}
{{/nav.item}}
{{#nav.item}}
{{#nav.link-to "navbars"}}Navbars{{/nav.link-to}}
{{/nav.item}}
{{/navbar.nav}}
{{/navbar.content}}
{{/bs-navbar}}
However I'm having strange results; the navbar is showing up 12 times in my page. For what it's worth, the toggle button doesn't do anything either - but that might be connected to the reason the navbar appears 12 times. See the following screenshot:
Here are the steps I took to set up this project:
ember new bootstrap-test
Inside /bootstrap-test:
ember install ember-bootstrap
ember g ember-bootstrap --bootstrap-version=4
Here is the contents of my ember-cli-build.js file:
/* eslint-env node */
'use strict';
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
let app = new EmberApp(defaults, {
'ember-bootstrap': {
'bootstrapVersion': 4,
'importBootstrapFont': false,
'importBootstrapCSS': false
}
});
// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
return app.toTree();
};
Finally, I'm using ember-cli version 2.14.2. Any help to figure this out would be greatly appreciated. Thank you!
It might be caused by re-rendering due to property update in didRender or didInsertElement hook. If that's the case then you surely you will get assertion error in console.
I always look for the first error, if there is more no of errors reported in the console. that helped me a lot in my development.

Access elements inside of a remote modal with vue.js

I'm read through the vue.js docs, but I am confused about how to load a partial and bind it to the vue instance.
As an example, with bootstrap's js, I can load a remote modal like this:
Add New Campaign
This loads a partial inside of my
<div id="modal></div>
Using vue, I have made the modal a component, and the partial will load, but I cannot get the partial's elements to bind to the vue instance. So any events inside of the modal such as
v-on:click.prevent="say('hi')"
won't work.
How do I bind elements added to the page after the vue instance is created?
You could use $mount
Parent vue instance declaration:
var vm = new Vue({...})
New Instance: (have this run after the dynamic content is loaded into your container)
var newContentInstance = vm.$addChild({
el: '#modal',
data: function data() {
return { something: '' };
}
});
newContentInstance.$mount();

How to set rootURL in Ember CLI

I'm trying to change the roolURL in an Ember CLI app. This is easy in a basic Ember app:
App.Router.reopen({
rootURL: '/blog/'
});
Doing this in an Ember CLI app throws the following exception:
Uncaught TypeError: Cannot read property 'reopen' of undefined
The reason why I'd like to do this is that I'm going to have multiple Ember CLI apps inside of a rails app. The URLs will look something like this:
/ --> rails
/foo --> rails
/api --> rails
/admin --> Ember CLI
/blog --> Ember CLI
You'd want to update your config/environment.js as follows:
module.exports = function(environment) {
var ENV = {
environment: environment,
baseURL: '/blog/'
see http://www.ember-cli.com/#deployments for environment specific configurations.