Bundle and use in another file - javascript

I want use material-ui.com in my react site.But i cant understand how add to my asp.net site.
I bundle with browserify.But i cant use it in my other pages.I take error in console
Uncaught TypeError: Cannot read property 'toUpperCase' of undefined .
var CalisanIslemListesi = React.createClass({
contextTypes: {
router: React.PropTypes.func
},
render:function(){
return (<p><RaisedButton /></p>);
}
});
My bundle file http://www.filedropper.com/materialuibundle

This was a very common problem for me too. This happens because MaterialUI needs some basic styles in order to work. You can find them here: http://material-ui.com/#/get-started
So unless you add these style to all components that use material-ui, it'll show the above error because it is looking for a dependency that is not available. If you go to the link above, it'll show you what styles it needs. However, it becomes very tedious to include those styles everytime, in every component that I make.
I use React Mixins. They're BASICALLY partial components that you can add to your component code. When you add a mixin to a component, what effectively happens is, the mixin gets expanded and added to your component. A lot like variables in string concatenation (Horrible example, I know, but it'll help you understand). When you add a variable to a string concatenation, the variable effectively gets replaced by its value. That is what happens with React Mixins.
Here is what I like to do:
Define a material.jsx file in my directory that goes like this (It is basically copied from their getting started page):
var React = require('react'),
mui = require('material-ui'),
ThemeManager = new mui.Styles.ThemeManager(),
injectTapEventPlugin = require("react-tap-event-plugin");
injectTapEventPlugin();
module.exports = {
childContextTypes: {
muiTheme: React.PropTypes.object
},
getChildContext: function() {
return {
muiTheme: ThemeManager.getCurrentTheme()
};
}
}
The above is just a mixin, it contains all styles required by Material-UI to function properly.
Now I'll just use the above module as a mixin in all Material-UI components.
var React = require('react'),
material = require('./material.jsx'),
mui = require('material-ui'),
FlatButton = mui.FlatButton
module.exports = React.createClass({
mixins: [material],
render: function() {
return <FlatButton>Hello</FlatButton>
}
})
In your code, if you make this material.jsx file and add the line mixins: [material] like I did, it'll all start working :)

Related

Importing / exporting Javascript Object Properties

I support a relatively complex legacy codebase, but am looking to modernise it a little by bringing in Webpack so that we'd have import & export capabilities in JS.
The problem I'm having is that we use a global object called App where we define and add different properties depending on the page. So for example we have the following file where we instantiate App (loaded on all pages):
app.js
const App = (() => {
const obj = {
Lib: {},
Util: {},
// etc
}
return obj;
})();
Then in another file we add to App.Lib just for the specific page that needs it:
lazyload.js
App.Lib.Lazyload = (() => {
// lazyload logic
})();
We simply concatenate the files during the bundling process, but obviously this is not ideal as none of the files have no knowledge of what goes on outside of it.
Exporting only seems to work for the top level object (where the object is defined), so anything I add to it elsewhere cannot be exported again. For example if I add export default App.Lib.Lazyload; at the end of lazyload.js and then try to import it elsewhere it will not import the Lazyload property.
Is there any way to get this to work without major refactor? If not, would you have any suggestions about the best way to handle it?
I don't think you can import Object.properties in JS. If you want to bundle specific packages (say Lazyload) for packages that need them, you might try:
//lazyload.js
export const LazyLoad = {
//lazyload logic
}
then somewhere else...
import {LazyLoad} from 'path/to/lazyload.js';
// assuming App has already been created/instantiated
App.Lib.Lazyload = LazyLoad;
Using Export Default...
//lazyload.js
const LazyLoad = {};
export default LazyLoad;
then...
import LazyLoad from 'path/to/lazyload.js';
App.Lib.LazyLoad = LazyLoad;
You can find help with Imports and Exports at MDN.

Scope import for an instance only

Good evening to everyone.
I'm not sure how can I explain my issue. I will show it to you by showing examples of the code and expected results. I could not use code from the real issue because the code is under license. I am very sorry for that and I will be glad of someone can help me solve my issue.
I'm using latest version of webpack, babel.
My application is spliced to three parts what are dynamically imported by each other. It is mean if I run split chunks plugin it will really create three clear files.
The parts are Core, Shared, Application. Where the Core only creating an instance of the application.
Result of the parts is bundled to single file. So it is linked by one html's script tag.
Project structure is:
src/app // For Application
src/core // For Core
src/shared // For Shared
In webpack configuration I am resolving alias for import ˙Editor$˙.
I renamed naming of variables because they are including project name.
resolve: {
alias: {
"Editor$": path.resolve('./src/app/statics/Editor.js'),
}
},
The content of Core file is
function createInstance(name, id) {
import("app").then(App => {
App(name, id)
});
}
The little bit of Application file is
imports...
import Framework from "./framework"
function createApp(name, id) {
new Framework({name, id}).$mount(...)
}
export default createApp
In the Application classes (what are instantiated inside Framework)
Is this import
import Editor from "Editor"
The Editor class is a singleton. But only for created instance.
class Editor {
static instance;
id = null;
constructor(){
if(this.constructor.instance){
return this.constructor.instance
}
this.constructor.instance = this
}
static get Instance() {
return this.instance || (this.instance = new this())
}
static get Id {
return this.Instance.id;
}
}
export default Editor
The issue is webpack dependency resolving. Because webpack puts and unify all imports to the top of the file.
So the imports are evaluated once through the life-cycle of the program.
But I need to tell webpack something like: There is an instance creation. Declare the new Editor singleton for this scope. Don not use the already cached one.
My another idea how to fix this is to set context for the instance. And in the Editor singleton create something like new Map<Context, Editor> if you get what I mean. But I did not find a way how to set a context for an instance or scope the import only for it.
I will appreciate any help. I am googling two days and still no have idea how to do it without rewriting all the imports.
Sorry for bugs in my English. I am not native speaker and my brain is not for languages.
Thanks everyone who take look into my issue.
How about recreating the Editor:
// Editor.js
class Editor {
// ...
}
let instance;
export function scope(cb) {
instance = new Editor();
cb();
instance = null;
}
export default function createEditor() {
if(!instance) throw Error("Editor created out of scope!");
return instance;
}
That way you can easily set up different scopes:
// index.js
import {scope} from "./editor";
scope(() => {
require("A");
require("B");
});
scope(() => {
require("C");
});
// A
import Editor from "./editor";
(new Editor()).sth = 1;
// B
import Editor from "./editor";
console.log((new Editor()).sth); // 1
// C
import Editor from "./editor";
console.log((new Editor()).sth); // undefined
// note that this will fail:
setTimeout(() => {
new Editor(); // error: Editor created out of scope
}, 0);
That also works for nested requires and imports as long as they are not dynamic.

import or require React components dynamically

I'm trying to import / require components dynamically, but somehow when I do it React complains. The require function does find it, but React throws an error saying it is missing some functions 't' etc.. All of this in an electron app.
I have a wizard setup (that is working, but not so elegant I think), where each page has it's own layout and jsx component. If I'd like to add a new page, I don't want to manage x-number of files, and at the moment I have to due to the setup I have currently. Below you can find what I want to achieve and what I'm doing now to achieve it. If there are any suggestions, code smells or better options please let me know as I'm quite new to React and ES2015 (as I'm from a C# background).
What I'm trying to achieve
export default class WizardPageContainer extends Component {
// Constructor
constructor(props) {
super(props);
}
// Render
render() {
const WizardPage = require(`./path/to/${this.props.step.id}`);
return (
<WizardPage step={this.props.step} />
);
}
}
How I'm currently doing it : which means I have to declare the imports / files first on top of the "WizardPageContainer" component.. Which means extra work and prone to errors/forgetting things. I should add, this code is working now ok, but I don't think this is elegant/future proof:
/* PAGES */
import WizardPage_Welcome from './pages/0.wizard.welcome';
import WizardPage_SystemCheck from './pages/1.wizard.systemCheck';
import WizardPage_SignIn from './pages/2.wizard.signIn';
import WizardPage_ExamCode from './pages/3.wizard.examCode';
import WizardPage_TakeExamination from './pages/4.wizard.takeExamination';
import WizardPage_Close from './pages/5.wizard.close';
const pages = [
WizardPage_Welcome,
WizardPage_SystemCheck,
WizardPage_SignIn,
WizardPage_ExamCode,
WizardPage_TakeExamination,
WizardPage_Close
];
/*/********************************************************************///
/* ******************************************************************** */
/* COMPONENT */
export default class WizardPageContainer extends Component {
// Constructor
constructor(props) {
super(props);
}
// Render
render() {
const WizardPage = pages[`${this.props.step.id}`];
return (
<WizardPage step={this.props.step} />
);
}
}
/*/********************************************************************///
I think it is about the "default". i have problem like this. Can you check this code;
https://github.com/robeio/robe-react-admin/blob/master/src/app/HasAuthorization.jsx#L10
Also you can check the example usage;
https://github.com/robeio/robe-react-admin/blob/master/src/app/HasAuthorization.jsx#L26
Your const pages needs to be an object, not an array.
You can see a working version I made of this here:
https://github.com/Frazer/meteor-react-nav/blob/master/lib/jsx/App.jsx
Best advice: Use Webpack to handle your imports, it's way more efficient than we could ever be.

How can I export 2 items from a Typescript Module

Scenario
I'm tasked with creating a Knockout Components based UI using Typescript.
This is something I've done hundreds of times in vanilla JS, but I just can't seem to get TS to generate a JS module in the correct format to be consumed by Require JS.
Ideally, what I'd like is for Typescript to generate identical output to that written in JS, but right now I'd just like to get things working.
The Javascript
This is the Javascript that I'm trying to get TS to generate, this is Javascript from a DIFFERENT project that does not use TS, and in that project when the JS is in this format, everything works fine.
define(["knockout", "text!./menubar.html"], function (ko, menubarTemplate)
{
function menubarViewModel()
{
var self = this;
self.menuBrand = ko.observable("Menu Brand");
self.menuItems = ko.observableArray([]);
self.load();
return self;
}
menubarViewModel.prototype.load = function ()
{
var self = this;
$.getJSON("data/menudata.json", function (data)
{
self.menuItems(data);
});
};
return { viewModel: menubarViewModel, template: menubarTemplate };
});
In my actual JS file that uses the component all I need to do is:
define(["jquery", "knockout", "bootstrap"], function ($, ko)
{
ko.components.register("menubar",
{
require: "application/components/menubar"
});
ko.applyBindings();
});
The HTML for the menubar component is just a simple chunk of plain HTML markup sprinkled with "data-bind" attributes where needed to inject the data into the component.
As I say, this JavaScript version works perfectly, but the client I'm working for at the moment wants this in Typescript, so the first challenge I need to tackle is how to return
return { viewModel: menubarViewModel, template: menubarTemplate };
from a typescript module.
Typescript so far
Iv'e had a small amount of success, for instance if I do:
import ko = require("knockout");
module HelloComponent {
export class HelloViewModel {
helloText = ko.observable<string>("Hello World");
}
}
That produces a JS class, that ko tries to load, but complains that it has no template.
This says to me that if I can take the TS class above and export the require text HTML from the same class, then I might just make this work.
If I further expand that class as follows:
import ko = require("knockout");
import helloTemplate = require("text!application/components/hello.html");
module HelloComponent {
export class HelloViewModel {
helloText = ko.observable<string>("Hello World");
}
var tmp = helloTemplate;
}
I've been trying to solve this for a couple of days now, and most of the experimentation I've tried has either failed, or appears to run in the chrome debugger, but produces no output in the component.
There are dozens of posts here on SO, but none of them apply to Knockout Components, all the others apply to page level standard binding, which is different from KO components, it's the same scenario with the various blog posts I've been reading.
If anyone has an insight on how to implement this as per the advice in the KnockoutJS docs but using TS rather than JS, then I'd love to hear your ideas.
Update 12-08-2015 (Based on James Reply)
After changing one of my components to match 'James Brantly' s answer, I now see the following in Visual Studio:
Update 13-08-2015 (Post testing James Reply)
Even with the errors shown above, I've now put together several components, all using the same methodology, and everything works perfectly.
Visual studio still flags these files as having errors, but it still allows me to compile the project, and Typescript still does what it needs to and compiles to JavaScript.
At this point, am marking the question as answered, as the initial question has been solved.
I think the key to your question is that you want the module to return something like { viewModel: menubarViewModel, template: menubarTemplate };. You do that like this:
import menubarTemplate = require('text!./menubar.html');
class MenubarViewModel{
}
export = {
viewModel: MenubarViewModel,
template: menubarTemplate
}
In the code :
import ko = require("knockout");
module HelloComponent {
You are mixing internal modules (the module keyword now called namespaces) and file based modules (the import keyword).
DON'T
Use External modules only:
import ko = require("knockout");
export class HelloViewModel {
helloText = ko.observable<string>("Hello World");
}
More : https://www.youtube.com/watch?v=KDrWLMUY0R0&hd=1

How do you manually mock one of your own files in Jest?

I'm trying to mock an object (which I created) in Jest so I can provide default behaviour within the react component (so the real implementation isn't used)
This is my react component ChatApp (it's very straight forward)
'use strict';
var React, ChatApp, ChatPanel, i18n;
React = require('react');
ChatPanel = require('./chat_panel');
i18n = require('../support/i18n');
ChatApp = React.createClass({
render() {
return (
<div className="chat-app">
<h1>{i18n.t("app.title")}</h1>
<ChatPanel />
</div>
);
}
});
module.exports = ChatApp;
So I have a custom I18n dependency that does translations (I18n is something I've written that is a wrapper for node-polyglot).
So I want to do a basic test to see if the H1 has the correct word in it, but I don't want to set jest.dontMock() on my I18n object, because I don't want it to use the real object in the ChatApp test.
So following the basic instructions on the jest website, I created a mocks folder and created a mock file for i18n, which generates a mock from the original object and then overrides the t method and adds a method to allow me to set the return string for t.
This is the mock object
'use strict';
var i18nMock, _returnString;
i18nMock = jest.genMockFromModule('../scripts/support/i18n');
_returnString = "";
function __setReturnString(string) {
_returnString = string;
}
function t(key, options = null) {
return _returnString;
}
i18nMock.t.mockImplementation(t);
i18nMock.__setReturnString = __setReturnString;
module.exports = i18nMock;
Now in my ChatApp test I require the mock in a before each, like so:
'use strict';
var React, ChatApp, TestUtils, path;
path = '../../../scripts/components/';
jest.dontMock( path + 'chat_app');
React = require('react/addons');
ChatApp = require( path + 'chat_app');
TestUtils = React.addons.TestUtils;
describe('ChatApp', () => {
beforeEach(() => {
require('i18n').__setReturnString('Chat App');
});
var ChatAppElement = TestUtils.renderIntoDocument(<ChatApp />);
it('renders a title on the page', () => {
var title = TestUtils.findRenderedDOMComponentWithTag(ChatAppElement, 'h1');
expect(title.tagName).toEqual('H1');
expect(title.props.children).toEqual('Chat App');
});
});
If i console.log the i18n object within the test then I get the correct mocked object, the __setReturnString also gets triggered (as if I console.log in that message I see the log).
However, if I console.log the i18n object within the actual React component then it gets a Jest mock but it doesn't get my Jest mock, so the t method is an empty method that doesn't do anything, meaning the test fails.
Any ideas what I'm doing wrong?
Thanks a lot
I've had trouble getting the __mocks__ folder working as well. The way I got around it is by using the jest.setMock(); method.
In your case, you would jest.setMock('../../../scripts/i18n/', require('../__mocks__/i18n');
Obviously, I am not certain of the location of your mock and the location of the real library you're using, but the first parameter should use the path where your real module is stored and the second should use the path where your mock is stored.
This should force your module and all modules that yours require (including React) to use your manually mocked i18n module.
Jest does automatic mocking. Just i18n = require('../support/i18n') should be enough. That's why you usually have to call jest.dontMock in the first place.
You can find more information here: https://facebook.github.io/jest/docs/automatic-mocking.html
What mattykuzyk mentions in his answer did not work at all for me :(
However, what I found out seemed to be the problem for me was the setup of jest: I used moduleNameMapper in the beginning, and for some reason these are never mocked...
So for me the first step was to instead move my module name mapped folder to the moduleDirectories to get anything to work.
After that, I could simply add a __mocks__ file adjacent to the actual implementation (in my case utils/translation.js and utils/__mocks__/translation.js).
As my translations.js default exports a translation function, I also default exported my mock. The entire __mocks__/translations.js is super simply and looks like this:
export default jest.fn((key, unwrap = false) => (
unwrap && `${key}-unwrapped` || `${key}-wrapped`
))
Although I haven't tested it, adding a __setReturnString should be easy enough, for me it was sufficient to actually return my translation key. Hope this helps!

Categories

Resources