How to mannage refs in react - javascript

This below code is to create svg shapes via React components.
Explanation of the code : I am doing composition in the react components first I have a parent g node and after that I have a child g node and in each child g node i have svg path.
what i am doing is : i am creating the shape and after that i am transforming that shape.
i have to transform the each shape individual the problem is that if we do this using the state of the parent it will work fine for the last element but what about is we want to change the transformation of the first element i.e we want to resize the shape
var ParentGroupThread = React.createClass({
getInitialState: function() {
return {
path: {}
};
},
render: function() {
Interfaces.DrawingThreads.ParentGroupThread = this;
var totalDrawing = Object.keys(this.state.path).length;
var drawings = [];
var pathState = this.state.path;
for (var i = 0; i < totalDrawing; i++) {
Interfaces.DrawingThreads.ParentThreadRef = pathState[i].ParentThreadId;
Interfaces.DrawingThreads.ThreadRef = pathState[i].threadIdPath;
drawings.push(React.createElement(ParentThread, {
ParentThreadId: pathState[i].ParentThreadId,
threadIdPath: pathState[i].threadIdPath,
d: pathState[i].d,
fillPath: pathState[i].fillPath,
strokePath: pathState[i].strokePath,
storkeWidthPath: pathState[i].storkeWidthPath,
classNamePath: pathState[i].classNamePath,
dataActionPath: pathState[i].dataActionPath,
dash: pathState[i].dash
}));
}
return React.createElement('g', {
id: 'ParentGroupThread',
key: 'ParentGroupThread_Key'
}, drawings);
}
});
var ParentThread = React.createClass({
getInitialState: function() {
return {
transformation: ''
};
},
render: function() {
Interfaces.DrawingThreads.ParentThread[Interfaces.DrawingThreads.ParentThreadRef] = this;
return React.createElement('g', {
id: this.props.ParentThreadId,
key: this.props.ParentThreadId + '_Key',
ref: this.props.ParentThreadId
},
React.createElement(Thread, {
threadIdPath: this.props.threadIdPath,
key: this.props.threadIdPath + '_Key',
d: this.props.d,
fillPath: this.props.fillPath,
strokePath: this.props.strokePath,
storkeWidthPath: this.props.storkeWidthPath,
transformPath: this.props.transformPath,
classNamePath: this.props.classNamePath,
dataActionPath: this.props.dataActionPath,
transformation: this.state.transformation,
dash: this.props.dash
})
);
}
});
var Thread = React.createClass({
getInitialState: function() {
return {
transformation: ''
};
},
render: function() {
Interfaces.DrawingThreads.Thread[Interfaces.DrawingThreads.ThreadRef] = this;
return React.createElement('path', {
id: this.props.threadIdPath,
d: this.props.d,
fill: this.props.fillPath,
stroke: this.props.strokePath,
strokeWidth: this.props.storkeWidthPath,
className: this.props.classNamePath,
'data-action': 'pathhover',
strokeDasharray: this.props.dash,
vectorEffect: 'non-scaling-stroke',
transformation: this.state.transformation,
ref: this.props.threadIdPath
});
}
});
ReactDOM.render(React.createElement(ParentGroupThread), document.getElementById('threads'));

Related

How to override javascript library object this.function(arg, function(){

I'm trying to override a function in the blessed-contrib tree module. However I think I'm missing something in the way of object inheritance. Any help would be greatly appreciated.
Original code:
function Tree(options) {
//...
this.rows = blessed.list({
top: 1,
width: 0,
left: 1,
style: options.style,
padding: options.padding,
keys: true,
tags: options.tags,
input: options.input,
vi: options.vi,
ignoreKeys: options.ignoreKeys,
scrollable: options.scrollable,
mouse: options.mouse,
selectedBg: 'blue',
});
this.append(this.rows);
this.rows.key(options.keys, function() {
var selectedNode = self.nodeLines[this.getItemIndex(this.selected)];
if (selectedNode.children) {
selectedNode.extended = !selectedNode.extended;
self.setData(self.data);
self.screen.render();
}
self.emit('select', selectedNode, this.getItemIndex(this.selected));
});
//...
I'm trying to override the this.rows.key(options.keys, function() { function in my own code. I'm trying to do something like the following but I'm not sure how the object path works for something that is ultimately of blessed-contrib.tree.list type in this case.
My code looks something like this:
"use strict";
var blessed = require('blessed'),
contrib = require('blessed-contrib');
//...
//create layout and widgets
var grid = new contrib.grid({rows: 1, cols: 2, screen: screen})
var tree = grid.set(0, 0, 1, 1, contrib.tree,
{
style: {
text: "red", fg: 'blue',
selected: {
bg: 'yellow', fg: 'white'
}
},
// keys: ['+', 'space'],
vi: true,
template: { lines: true },
label: 'Filesystem Tree'
})
// monkeypatch contrib.tree.rows.key(options.keys, function() {}
// save the original
var old_tree_rows_key = tree.rows.key;
//tree.rows.key = function(options_keys) {
tree.rows.key = function(options_keys) {
var selectedNode = self.nodeLines[this.getItemIndex(this.selected)];
// handle items in options.keys array on my own for custom purposes
// ...
// Code I want commented out:
// if (selectedNode.children) {
// selectedNode.extended = !selectedNode.extended;
// self.setData(self.data);
// self.screen.render();
// }
self.emit('select', selectedNode, this.getItemIndex(this.selected));
};
//...
Ok, Thanks #Bergi! His clue led me to javascript - Why is it impossible to change constructor function from prototype?. I was thinking that I should have deeper access to the object and that I wouldn't have to copy the entire constructor -but I was wrong.
my final code looks like this:
"use strict";
var blessed = require('blessed'),
contrib = require('blessed-contrib'),
Node = blessed.Node,
Box = blessed.Box;
//...
// monkeypatch contrib.tree constructor to change keyhandler
// save the original
var old_tree = contrib.tree.prototype;
//function Tree(options) {
contrib.tree = function(options) {
if (!(this instanceof Node)) return new contrib.tree(options);
var self = this;
options = options || {};
options.bold = true;
this.options = options;
this.data = {};
this.nodeLines = [];
this.lineNbr = 0;
Box.call(this, options);
//...
this.rows.key(options.keys, function() {
var selectedNode = self.nodeLines[this.getItemIndex(this.selected)];
// if (selectedNode.children) {
// selectedNode.extended = !selectedNode.extended;
// self.setData(self.data);
// self.screen.render();
// }
self.emit('select', selectedNode, this.getItemIndex(this.selected));
});
//...
};
// restore binding
contrib.tree.prototype = old_tree;
var tree = grid.set(0, 0, 1, 1, contrib.tree,
{
style: {
text: "red", fg: 'blue',
selected: {
bg: 'yellow', fg: 'white'
}
},
// keys: ['+', 'space'],
vi: true,
template: { lines: true },
label: 'Filesystem Tree'
})
//...

How to render unknown/variable number of React elements

I have this React component that looks like this:
var TestResult = React.createFactory(React.createClass({
displayName: 'test-result',
getInitialState: function getInitialState() {
return {
active: false,
testLines: [] //this value will update after AJAX/WebWorker completes
};
},
makeNewState: function makeState(data) {
this.setState(data);
},
componentDidMount: function () {
var self = this;
var testPath = this.props.testPath;
setTimeout(function(){
$.get(testPath).done(function (msg) {
var myWorker = new Worker('/js/workers/one.js');
myWorker.postMessage(msg);
myWorker.onmessage = function (msg) {
self.setState({testLines: msg.data.testLines});
};
}).fail(function (err) {
console.error(err);
});
}, Math.random()*2000);
},
render: function() {
var self = this;
return React.createElement('p', {
className: this.state.active ? 'active' : '',
onClick: this.clickHandler,
},
self.state.testName, ' ', self.state.testLines, React.createElement('b', null, 'Pass/fail')
);
}
}));
what I want is to render a variable number of components in the render function - the variable number is related to number of elements in the testLines array.
So, in order to do that, I might try changing the render method above:
render: function() {
var self = this;
return React.createElement('p', {
className: this.state.active ? 'active' : '',
},
self.state.testName, ' ', React.createElement('div', self.state.testLines, React.createElement('b', null, 'Pass/fail')
);
}
so what I am trying to do is pass testLines, which is an array of React.createElement results, to React.createElement. Is this the correct way of doing it? "It" meaning rendering a variable number of React elements.
What you have to do is map over the array and create each of the sub-elements, then render those:
render: function() {
var lines = this.state.testLines.map(function(line, i) {
// This is just an example - your return will pull information from `line`
// Make sure to always pass a `key` prop when working with dynamic children: https://facebook.github.io/react/docs/multiple-components.html#dynamic-children
return (
<div key={i}>I am a line!</div>
);
});
return (
<div id='lineContainer'>
{lines}
</div>
);
};

Ionic Angular Js Factory services, factory have another factory

Sorry for beginner question , how to make the factory have another factory?I need the foods data have link to restaurant (like one to many relationship).
This is my code:
.factory('Foods', function() {
var foods = [{
id: 1,
name: 'Food 1',
price: '$12',
category:'Appetizer',
imageSrc: 'img/new_food1.jpg',
restaurant:Restaurants.get(1),
}];
return {
all: function() {
return foods;
},
remove: function(food) {
foods.splice(foods.indexOf(food), 1);
},
get: function(foodId) {
for (var i = 0; i < foods.length; i++) {
if (foods[i].id === parseInt(foodId)) {
return foods[i];
}
}
return null;
}
};
})
And this is my factory for restaurant code:
.factory('Restaurants', function() {
var restaurants = [{
id: 1,
name: 'Restaurant 1',
imageSrc: 'img/resto1.jpg'
}];
return {
all: function() {
return restaurants;
},
remove: function(restaurant) {
restaurants.splice(restaurants.indexOf(restaurant), 1);
},
get: function(restaurantId) {
for (var i = 0; i < restaurants.length; i++) {
if (restaurants[i].id === parseInt(restaurantId)) {
return restaurants[i];
}
}
return null;
}
};
});
But it is makes the data error. How to make the array have object value (Restaurant)? Thanks...
Services can require other services. You can use the Angular auto injection by using a parameter with the name of your service :
.factory('Foods', function(Restaurants) {
// ...
Restaurants.get(42);
// ...
});

How to use jQuery $.extend(obj1, obj2)

I'm trying to create a button class that extends an AbstractComponent class using $.extend() but the functions in AbstractComponent aren't available when I'm constructing the button.
The specific error I'm receiving is:
Uncaught TypeError: Object [object Object] has no method 'setOptions'
var Button = {};
var abstract = new AbstractComponent;
$.extend(Button,abstract);
//debugger;
//this.setOptions is available here
Button = function(options) {
'use strict';
var defaultOptions = {
templateName: '#button-tmpl',
title: "Label goes here",
type: "primary",
size: "medium",
disabled: null,
autosave: null,
href: null,
onclick: null
};
//debugger
//this.setOptions is not available here
this.setOptions(options, defaultOptions);
this.checkRequiredKeys('title');
return this;
};
Button.prototype.updateOptions = function() {
var options = this.options;
if (options.href === null) {
options.href = 'javascript:;';
}
if (options.disabled === null) {
options.disabled = 'disabled';
}
if (options.autosave === true) {
options.autosave = 'ping-autosave';
}
};
AbstractComponent.js
var AbstractComponent = function() {
console.log('this will be the constructor for elements extending this class');
};
AbstractComponent.prototype.show = function() {
this.render();
};
AbstractComponent.prototype.close = function() {
// stop listeners and remove this component
this.stopListening();
this.remove();
};
AbstractComponent.prototype.getTemplateName = function() {
return this.options.templateName;
};
AbstractComponent.prototype.checkRequiredKeys = function() {
var errors = new Array();
if (typeof this.getTemplateName() === "undefined") {
errors.push('templateName');
}
for (var i = 0; i < arguments.length; i++) {
if (!this.options.hasOwnProperty(arguments[i])) {
errors.push(arguments[i]);
}
}
if (errors.length > 0) {
throw new Exception("Required property(s) not found:" + errors.join(', ') + " in " + this.toString());
}
};
AbstractComponent.prototype.getElement = function() {
'use strict';
if(!this.options.updated) {
this.updateOptions();
}
return new AbstractView(this.options).render().$el;
};
AbstractComponent.prototype.updateOptions = function() {
this.options.updated = true;
return true;
};
AbstractComponent.prototype.getHtml = function() {
return this.getElement().html();
};
AbstractComponent.prototype.setOptions = function(options, defaultOptions) {
this.options = _.defaults(options, defaultOptions);
};
AbstractComponent.prototype.toString = function() {
return "Component" + this.getTemplateName() + "[id=" + this.options.id + "]";
};
jQuery extend is for moving properties from one (or more) object(s) to another object.
$.extend({}, {
foo: 10,
bar: 20
});
You should use prototypal inheritance isntead
function Button(options) {
'use strict';
var defaultOptions = {
templateName: '#button-tmpl',
title: "Label goes here",
type: "primary",
size: "medium",
disabled: null,
autosave: null,
href: null,
onclick: null
};
//debugger
//this.setOptions is not available here
this.setOptions(options, defaultOptions);
this.checkRequiredKeys('title');
return this;
};
Button.prototype = new AbstractComponent;

KnockOutJS trigger parent function on child subscribe

I am currently trying to learn KnockOutJS. I thought it would be a great idea to create a simple task-list application.
I do not want to write a long text here, let's dive into my problem. I appreciate all kind of help - I am new to KnockOutJS tho!
The tasks are declared as followed:
var Task = function (data) {
var self = this;
self.name = ko.observable(data.name);
self.status = ko.observable(data.status);
self.priority = ko.observable(data.priority);
}
And the view model looks like this
var TaskListViewModel = function() {
var self = this;
self.currentTask = ko.observable();
self.currentTask(new Task({ name: "", status: false, priority: new Priority({ name: "", value: 0 }) }));
self.tasksArr = ko.observableArray();
self.tasks = ko.computed(function () {
return self.tasksArr.slice().sort(self.sortTasks);
}, self);
self.sortTasks = function (l, r) {
if (l.status() != r.status()) {
if (l.status()) return 1;
else return -1;
}
return (l.priority().value > r.priority().value) ? 1 : -1;
};
self.priorities = [
new Priority({ name: "Low", value: 3 }),
new Priority({ name: "Medium", value: 2 }),
new Priority({ name: "High", value: 1 })
];
// Adds a task to the list
// also saves updated task list to localstorage
self.addTask = function () {
self.tasksArr.push(new Task({ name: self.currentTask().name(), status: false, priority: self.currentTask().priority() }));
self.localStorageSave();
self.currentTask().name("");
};
// Removes a task to a list
// also saves updated task list to localstorage
self.removeTask = function (task) {
self.tasksArr.remove(task);
self.localStorageSave();
};
// Simple test function to check if event is fired.
self.testFunction = function (task) {
console.log("Test function called");
};
// Saves all tasks to localStorage
self.localStorageSave = function () {
localStorage.setItem("romaTasks", ko.toJSON(self.tasksArr));
};
// loads saved data from localstorage and parses them correctly.
self.localStorageLoad = function () {
var parsed = JSON.parse(localStorage.getItem("romaTasks"));
if (parsed != null) {
var tTask = null;
for (var i = 0; i < parsed.length; i++) {
tTask = new Task({
name: parsed[i].name,
status: parsed[i].status,
priority: new Priority({
name: parsed[i].priority.name,
value: parsed[i].priority.value
})
});
self.tasksArr.push(tTask);
}
}
};
self.localStorageLoad();
}
What I want to do in my html is pretty simple.
All tasks I have added are saved to localStorage. The save function is, as you can see, called each time an element has been added & removed. But I also want to save as soon as the status of each task has been changed, but it is not possible to use subscribe here, such as
self.status.subscribe(function() {});
because I cannot access self.tasksArr from the Task class.
Any idea? Is it possible to make the self.tasksArr public somehow?
Thanks in advance!
Try this:
self.addTask = function () {
var myTask = new Task({ name: self.currentTask().name(), status: false, priority: self.currentTask().priority() })
myTask.status.subscribe(function (newValue) {
self.localStorageSave();
});
self.tasksArr.push(myTask);
self.localStorageSave();
self.currentTask().name("");
};

Categories

Resources