Export React mixin in a separated file - javascript

I am trying to separate the SetIntervalMixin into a different file that the component class file. Maybe I am not fully understand how module.export works but... If I do like this:
module.exports = {
componentWillMount: function() {
this.intervals = [];
},
setInterval: function() {
this.intervals.push(setInterval.apply(null, arguments));
},
componentWillUnmount: function() {
this.intervals.map(clearInterval);
}
};
inside a SetIntervalMixin.js, then it works fine using from the component:
var SetIntervalMixin = require('../util/mixins/SetIntervalMixin')
But if I write it like this:
var SetIntervalMixin = {
componentWillMount: function() {
this.intervals = [];
},
setInterval: function() {
this.intervals.push(setInterval.apply(null, arguments));
},
componentWillUnmount: function() {
this.intervals.map(clearInterval);
}
};
module.export = SetIntervalMixin;
It doesn't work (undefined when trying to call setInterval()). I think something is missing after:
SetIntervalMixin = ...
Like when you define a component, you use:
var yourComponent = React.createClass(...
Is there is something similar like a React.createMixin(.. ? Or how would be the best way to do this.
Thanks.

Your code is right, you just have a typo in the second version (should be module.exports instead of module.export):
var SetIntervalMixin = {
componentWillMount: function() {
this.intervals = [];
},
setInterval: function() {
this.intervals.push(setInterval.apply(null, arguments));
},
componentWillUnmount: function() {
this.intervals.map(clearInterval);
}
};
module.exports = SetIntervalMixin;

Related

Making a ES6 class out of Angular 1.5+ component and getting function callbacks to work

var app = angular.module('testApp', []);
class Component {
constructor(app, name, template, as, bindings) {
this.bindings = bindings;
this.config = {}
this.config.template = template;
this.config.controllerAs = as;
// pre-create properties
this.config.controller = this.controller;
this.config['bindings'] = this.bindings;
app.component(name, this.config);
console.log("Inside Component ctor()");
}
addBindings(name, bindingType) {
this.bindings[name] = bindingType;
}
controller() {
}
}
class App extends Component {
constructor(app) {
var bindings = {
name: "<"
};
super(app, "app", "Hello", "vm", bindings);
}
controller() {
this.$onInit = () => this.Init(); // DOESN'T WORK
/*
var self = this;
self.$onInit = function () { self.Init(); }; // DOESN'T WORK
*/
/*
this.$onInit = function () { // WORKS
console.log("This works but I don't like it!");
};
*/
}
Init() {
console.log("Init");
}
onNameSelected(user) {
this.selectedUser = user;
}
}
var myApp = new App(app);
<div ng-app="testApp">
<app></app>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>
I'm trying to "classify" angular 1.5's .component(). I can get most of it figured out but when I try to assign a class method for $onInit it doesn't work. I've tried assigning to it and using arrow notation to call back to the class method but neither work. It does work if I assign an anonymous function directly but I don't want to do that. I want those functions to point to class methods because I find it cleaner.
So ultimately I want my App classes Init() method to get called for $onInit(). Is it possible?

React mixin used to add multiple subscribes to component

I am trying to use a mixin to subscribe/ unsubscribe to messages in my component, I have the below code, can anyone please tell me if there is a better way to do this rather than a push for each subscription?
UPDATED: keep getting error, Uncaught TypeError: this.subscribeToChannel is not a function
Thanks in advance
var Icon = require('../partials/Icon');
var React = require('react');
var postal = require('postal');
var basketChannel = postal.channel("basket"),
BasketService = require('../../services/BasketService'),
subscriptionsMixin = require('../mixins/subscriptionToChannelsMixin');
var BasketLauncher = React.createClass({
mixins: [subscriptionsMixin],
render: function() {
return (
<button className="pull-right" onClick={this.props.handleClick}>
<Icon type="user" /> {this.getPeopleCount()} People
</button>
);
},
updateBasketTotal: function() {
BasketService.getBasketTotal(function(data){
this.setState({
selectedPeopleCount: data.TotalMembers
});
}.bind(this));
},
componentDidMount: function() {
var comp = this;
comp.updateBasketTotal();
this.subscribeToChannel(basketChannel,"selectAll",function (data) {
BasketService.selectAll(data.selectAll, function () {
comp.updateBasketTotal();
});
});
this.subscriptions.push(
basketChannel.subscribe("updateBasketCount", function () {
comp.updateBasketTotal();
})
);
this.subscriptions.push(
basketChannel.subscribe("removePersonFromBasket", function (data) {
BasketService.removePerson(data.personId,function(){
comp.updateBasketTotal();
});
})
);
this.subscriptions.push(
basketChannel.subscribe("addPersonToBasket", function (data) {
BasketService.addPerson(data.personId,function(){
comp.updateBasketTotal();
} );
})
);
this.subscriptions.push(
basketChannel.subscribe("addArrayToBasket", function (data) {
BasketService.addPerson(data.arrayToPush,function(){
comp.updateBasketTotal();
} );
})
);
},
getPeopleCount: function(){
return this.state.selectedPeopleCount;
},
getInitialState: function() {
return {
subscriptions: [],
selectedPeopleCount:0
};
},
componentWillMount: function() {
var page = this;
}
});
module.exports = BasketLauncher;
Mixin:
var React = require('react');
var postal = require('postal');
var subscriptionsMixin = {
getInitialState: function() {
return {
subscriptions: []
};
},
componentWillUnmount:function() {
for (i = 0; i < this.subscriptions.length; i++) {
postal.unsubscribe(this.state.subscriptions[i]);
}
},
subscribeToChannel:function(channel,message,callback){
this.state.subscriptions.push(
channel.subscribe(message, callback)
);
}
};
It looks like your mixin is missing the export line
module.exports = subscriptionsMixin;
I wouldn't put native functions in a mixin (componentDidMount ...etc).
Keep those functions inside your class and put inner function like "basketChannel.subscribe" in the mixin.
Actually I would put the subscribtion object in the mixin itself and would attach the subscriptions functions as prototype.
Hope it helps
Edit: Idk if it's the source of your problem but you set getInitialState twice, once in your mixin and once in your class

Jquery plugin access var from method using prototype

I have the following javascript code using http://fr.jqueryboilerplate.com/
;(function ($, window, document, undefined) {
var pluginName = "PluginName",
defaults = {
overlay: {
BgColor: "#000",
opacity: "0.6"
}
};
function Plugin(element, options) {
this.element = $(element);
this.options = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype = {
init: function () {
console.log("init");
var overlay = jQuery("<div/>", {
id: "ModalOverlay",
click: function () {
Plugin.prototype.Mymethod();
}
});
},
Mymethod: function () {}
};
Anyone could teach me how can access to variables, whose are into
function Plugin(){}
from
Mymethod: function() {}
maybe something like that :
add store object
Plugin.prototype = {
store: {
_overlay: null
}
Into init function
Plugin.prototype.store._overlay = overlay;
And then access it like :
Mymethod: function () {
console.log(Plugin.prototype.store._overlay);
},
I'm pretty sure that's work, but i think that's very dirty.
Try this code, I have not tested it. but worth try . If does not work let me know and i will delete.
Plugin.prototype = {
init: function () {
var myThis=this;
console.log("init");
var overlay = jQuery("<div/>", {
id: "ModalOverlay",
click: function () {
myThis.Mymethod();
}
});
},
Mymethod: function () {
alert(this._name);
alert(this.options);
alert(this.options.overlay);
console.log(this.options.overlay);
}
};

How to extends a javascript object?

I made a simple example of my problem with a babel object :
function babel(){
this.english = {
hello: function () { alert('hello'); },
goodbye: function () { alert('goodbye'); }
teeshirt: function () { alert('T-shirt'); }
}
}
Now, I want to extends this object :
babel.prototype.french = {
bonjour: function () { alert('bonjour'); },
aurevoir: function () { alert('au revoir'); }
}
But what if I need to use an existing function define before ?
babel.prototype.french = {
bonjour: function () { alert('bonjour'); },
aurevoir: function () { alert('aurevoir'); },
teeshirt: function () { this.english.teeshirt(); }
}
What I could do is :
var say = new babel();
(function (_this) {
babel.prototype.french = {
bonjour: function () { alert('bonjour'); },
aurevoir: function () { alert('aurevoir'); },
hello: function () { _this.english.hello(); }
}
})(say);
But in this case, I will always use the context of the say object, isn't it ?
The problem is, that in teeshirt function call this points to the french object, not babel object. If you have to access parent object, you should store reference to it somewhere. For example you can change your constructor like this:
function babel(){
this.english = {
parent: this,
hello: function () { alert('hello'); },
goodbye: function () { alert('goodbye'); }
teeshirt: function () { this.parent.french.something(); }
}
}
But as you can see, there is a problem if you don't create object in constructor. I don't see any 'nice' approach, but you can do this:
function babel(){
this.english = {
parent: this,
hello: function () { alert('hello'); },
goodbye: function () { alert('goodbye'); }
teeshirt: function () { this.parent.french.something(); }
};
for (var i in babel.prototype) {
this[i].parent = this;
}
}
Then your french will look like this:
babel.prototype.french = {
bonjour: function () { alert('bonjour'); },
aurevoir: function () { alert('aurevoir'); },
teeshirt: function () { this.parent.english.teeshirt(); }
}
While the question as asked does bring up all the fascinating issues with JavaScript's this and prototypal inheritance, I would suggest simplifying the whole problem and refactoring your objects. There are a couple ways to do this.
If the English version of teeshirt is the default, it should be in the object which is at the end of the prototype chain. That is, a French object would have as its prototype an English object. The French object would simply not contain a teeshirt member. This is similar to the way resource bundles work.
Now this idea may not work for you, because the relationship among the different bundles may be complex: perhaps sometimes Engish is a fallback sometimes but not other times. In this case, see if you can make your babel objects all singletons (i.e., just plain objects).
var babel = {}
babel.english = {
hello: function () { alert('hello'); },
goodbye: function () { alert('goodbye'); },
teeshirt: function () { alert('T-shirt'); }
}
babel.french = {
bonjour: function () { alert('bonjour'); },
aurevoir: function () { alert('aurevoir'); },
teeshirt: function () { babel.english.teeshirt(); }
}
babel.english.teeshirt();
babel.french.teeshirt();
Try it at http://jsfiddle.net/yRnLj/
I realize this looks like a complete avoidance of your interesting question. But if you only need one copy of each language bundle, it is a lot simpler. :-)

Javascript optional parameters for callbacks

I want to do something like $.ajax() success and error callbacks.
This is what I have so far:
var FileManager = {
LoadRequiredFiles: function (onLoadingCallback, onCompleteCallback) {
//Not sure what to do here
this.OnLoading = onLoadingCallback;
this.OnCompleteCallback = onCompleteCallback;
this.OnLoading();
this.OnComplete();
},
OnLoading: function () {
//empty by default
}
OnComplete: function () {
//empty by default
}
};
//I want to do something like this:
FileManager.LoadRequiredFiles({OnLoading: function() {
alert('loading');
}
});
How do I fix this up properly? I'm using FileManager as my namespace.
You can check if the functions are defined:
var FileManager = {
LoadRequiredFiles: function (config) {
config = config || {};
this.OnLoading = config.onLoadingCallback;
this.OnCompleteCallback = config.onCompleteCallback;
if(typeof this.OnLoading =='function') {
this.OnLoading();
}
//Or use the shortcut:
if(this.OnComplete) {
this.OnComplete();
}
}
};
FileManager.LoadRequiredFiles(
{
onLoadingCallback: function() {
alert('loading');
}
}
);

Categories

Resources