React table rows population issue - javascript

I am trying to generate an html table based on a Rest web service call using React. Only table header was displayed. The table rows are blank. If I debug it, after line
tableModel.rows = this.state.rows;
tableModel.rows was 'undefined'.
I counldn't figure out what's the issue.
<!DOCTYPE html>
<html>
<head>
<title>React Flux</title>
<script src="https://fb.me/react-0.13.3.js"></script>
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
</head>
<body>
<div id="container" style="color:red"></div>
<script type="text/jsx">
var tableModel = {
cols: ["id", "name"],
rows: [],
}
var Table = React.createClass({
getInitialState: function () {
return {text: ''};
},
componentDidMount: function(){
$.ajax({
url: "http://localhost:8080/rest/user/findAll"
}).then(function(data) {
this.setState({
rows: data});
}.bind(this))
},
render: function() {
tableModel.rows = this.state.rows;
var _self = this;
var thead = React.DOM.thead({},
React.DOM.tr({},
this.props.cols.map(function (col) {
return React.DOM.th({}, col);
})));
var tbody = this.props.rows.map(function (row) {
return React.DOM.tr({},
_self.props.cols.map(function (col) {
return React.DOM.td({}, row[col] || "");
}));
});
return React.DOM.table({}, [thead, tbody]);
}
});
React.render(<Table cols={tableModel.cols} rows={tableModel.rows} />, container);
</script>
</body>
</html>

When your Table setState, it's render function will be recall, but why do you think it's props would be repopulate? It stay the same, mean Table this.props.rows === []. You could fix it by put the tableModel into Table state and using this.state instead of this.props, or wrap another class to Table to manage data fetching and populate data to Table class.

Related

How to execute script file before another script in layout page?

Inside my layout page i wanna run a script for translate the text of some enumumerators.
My layout looks like this:
<html>
<head>
...
<script src="~/js/ViewModels/Helpers/Translation.js"></script>
<script src="~/js/ViewModels/Helpers/Enumerators.js"></script>
...
</head>
<body>
...
</body>
</html>
My translation script:
'use strict';
var jsonTranstation = null;
$(function () {
getjson();
});
const getjson = () => {
$.getJSON('/lib/translation/en-EN.json', function (data) {
jsonTranstation = data;
});
}
const Translation = (value, ViewModel) => {
let a = null;
if (jsonTranstation ) {
a = jsonTranstation[ViewModel][value];
return a;
}
return '--';
}
My Enumerators script:
'use strict'
const EnumToolBar = {
NEW: { text: Translation('New', 'EnumToolBar'), prefixIcon: 'e-add', id: 'NEW' }
}
My JSON file (en-EN.json):
{
"EnumToolBar": {
"New": "New Value"
}
}
Using EnumToolBar.NEW.text in HomePage returns '--' instead of 'New Value'.
There are any way to read first script and the respective json file before any other script?

Adding data in node of jstree through dropdown not working properly

I am trying to add a dropdown in a node and want to be able to create and remove the nodes. I am able to do that but whenever i create/remove a node the dropdown values that i have selected are removed from where the node is created or removed. I am using select2 for dropdown if that helps.
below is the link for demonstration
https://www.arsallodhi.com/jstree/index.html
thanks in advance
I think redraw method is called which does removes the values. So i tried to catch it but couldnt.
<html>
<head>
<style>
.jstree-default .jstree-node, .jstree-leaf {
min-height: 35px !important;
}
.jstree-open .jstree-node {
padding-top: 15px !important;
}
</style>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/css/select2.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css"/>
</head>
<body>
<div id="jstreee">
<ul>
<li class="jstree-open">
Organization
</li>
</ul>
</div>
<script src="https://kendo.cdn.telerik.com/2019.2.514/js/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<script>
function formatDropdown1(option) {
if (option.id) {
return option.text;
} else {
return '';
}
};
function addTagValueClass() {
$('.tag').select2({
placeholder: '',
allowClear: true,
tags: true,
templateSelection: formatDropdown1,
});
}
var counter = 0;
function customMenu2(node) {
var position = 'inside';
var parent;
var selected_id;
selected_id = parent = $('#jstreee').jstree('get_selected');
counter++;
var node_data;
node_data = "<li class='node-li'><select data-live-search='true' class='tag' placeholder='Tag'><option></option><option value='volvo'>Project</option><option value='saab'>Owner</option><option value='mercede'>Department</option><option value='audi'>Business Unit</option></select></li>"
var items = {
createItem: {
label: "Add Node",
action: function () {
$('#jstreee').jstree().create_node(parent, {"id": "ajson5" + counter, "text": node_data}, position
, function () {
addTagValueClass();
$('#jstreee').jstree().open_node('#' + parent);
});
}
},
deleteItem: {
label: "Remove Node",
action: function () {
if (selected_id != "j1_1") {
$('#jstreee').jstree().delete_node(selected_id);
addTagValueClass();
}
}
}
};
return items;
}
$('#jstreee').on('open_node.jstree', function (e, data) {
addTagValueClass();
});
$('#jstreee').jstree({
"core": {"check_callback": true, "themes": {"icons": false}, "toggle_node": true}, // so that modifying operations work
"plugins": ["contextmenu"], contextmenu: {items: customMenu2}
});
</script>
</body>
</html>
I want that the values which i have set through the dropdown remain even when a node is created or removed.

Treeview onNodeSelected not firing

Im using the Jon Miles treeview from https://github.com/jonmiles/bootstrap-treeview
I have generated a JSON data structure and the treeview displays nicely, however I cannot make the onNodeSelected event fire.
JS:
<script src="~/Scripts/jquery-3.1.1.js"></script>
<script src="~/Scripts/bootstrap-treeview.js"></script>
<link href="~/Content/bootstrap.css" rel="stylesheet" />
<script>
$(function () {
var defaultData = #Html.Raw(broadcaster.GetTreeViewData()); //Getting data from C# data structure
$('#tree').treeview({
color: "#428bca",
data: defaultData,
levels: 2
});
});
$('#tree').treeview({
onNodeSelected: function(event, data) {
alert('selected:')
}});
</script>
HTML:
<li>
<div id="tree"></div>
</li>
edit:
also tried the jQuery on()but no luck - nothing happens.
$('#tree').on('nodeSelected', function(event, data) {
alert('selected:')
you are initializing nodes 2 times..
it should be like this...
$(function () {
var defaultData = #Html.Raw(broadcaster.GetTreeViewData()); //Getting data from C# data structure
$('#tree').treeview({
color: "#428bca",
data: defaultData,
levels: 2,
onNodeSelected: function(event, data) {
alert('selected:')
}
});
});

Getting a json from collection to view in backbone.js

I am new to backbone.js and is having some problem with my app. I have a collection which relies on a json data source. I am able to console.log the json in my parse method. Is that enough to bind the collection to my view? I don't understand the use of fetch method.
My collection looks like as follows,
(function (collections,model) {
collections.Directory = Backbone.Collection.extend({
initialize : function(){
console.log('we are here');
},
model:model.item,
url:'collections/json/data.json',
parse:function(response){
console.log(response);
return response;
}
});
})(app.collections,app.models);
And my master view looks like this,
(function(views,collections){
views.masterView = Backbone.View.extend({
el : $("#contacts"),
initialize : function(){
console.log('view initialize inside render');
this.render();
this.$el.find("#filter").append(this.createSelect());
this.on("change:filterType", this.filterByType, this);
this.collection.on("reset", this.render, this);
this.collection.on("add", this.renderContact, this);
//console.log('we are here'+app.collections.CollectionItems.fetch());
console.log('view initialize');
},
render : function(){
this.$el.find("article").remove();
_.each(this.collection.models,function(item){
this.renderContact(item);
},this);
},
renderContact: function (item) {
views.contactView = new app.views.ContactView({
model: item
});
this.$el.append(contactView.render().el);
},
getTypes : function () {
return _.uniq(this.collection.pluck("Qno"));
},
createSelect : function () {
var select = $("<select/>", {
html: "<option value='all'>All</option>"
});
_.each(this.getTypes(), function (item) {
var option = $("<option/>", {
value: item.toLowerCase(),
text: item.toLowerCase()
}).appendTo(select);
});
return select;
},
events: {
"change #filter select": "setFilter",
"click #add": "addContact",
"click #showForm": "showForm"
},
setFilter : function(e){
this.filterType = e.currentTarget.value;
this.trigger("change:filterType");
},
filterByType: function () {
if (this.filterType === "all") {
this.collection.reset(contacts);
routerURL.navigate("filter/all");
} else {
this.collection.reset(contacts, { silent: true });
var filterType = this.filterType,
filtered = _.filter(this.collection.models, function (item) {
return item.get("type").toLowerCase() === filterType;
});
this.collection.reset(filtered);
routerURL.navigate("filter/"+filterType);
}
},
addContact : function(e){
e.preventDefault();
var contModel = {};
$("#addContact").children("input").each(function(i, el){
if($(el).val() !== "")
contModel[el.id] = $(el).val();
});
contacts.push(contModel);
if (_.indexOf(this.getTypes(), contModel.type) === -1) {
this.collection.add(new Contact(contModel));
this.$el.find("#filter").find("select").remove().end().append(this.createSelect());
} else {
this.collection.add(new Contact(contModel));
}
},
showForm : function(){
this.$el.find("#addContact").slideToggle();
}
});
})(app.views,app.collections);
my model is very simple and looks like this,
(function ( models ) {
models.Item = Backbone.Model.extend({
defaults :{Qno:'1',Desc:'hello'}
});
})( app.models );
ihave one js file instantiatin viewsand collections
(function () {
window.app = {};
app.collections = {};
app.models = {};
app.views = {};
app.mixins = {};
$(function(){
app.collections.CollectionItems = new app.collections.Directory();
//app.collections.CollectionItems.fetch();
//console.log(app.collections.CollectionItems.fetch());
app.collections.CollectionItems.fetch({
success: function (collection,response) {
console.log(response);
}
});
//console.log(app.collections.CollectionItems.toJSON());
console.log('coll started');
app.views.app = new app.views.masterView({collection: app.collections.CollectionItems});
console.log('view is jus about fine!!');
//app.views.pagination = new app.views.PaginatedView({collection:app.collections.paginatedItems});
});
var ContactsRouter = Backbone.Router.extend({
routes: {
"filter/:type": "urlFilter"
},
urlFilter: function (type) {
master.filterType = type;
master.trigger("change:filterType");
}
});
var routerURL = new ContactsRouter();
Backbone.history.start();
})();
my landing page looks like this with a template in it
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Backbone.js Web App</title>
<link rel="stylesheet" href="css/screen.css" />
</head>
<body>
<div id="contacts">
</div>
<script id="contactTemplate" type="text/template">
<h1><%= Qno %></h1>
</script>
<script src="js/jquery.js"></script>
<script src="js/underscore-min.js"></script>
<script src="js/backbone-min.js"></script>
<script src="app.js"></script>
<script src="collections/Directory.js"></script>
<script src="models/item.js"></script>
<script src="views/masterView.js"></script>
<script src="views/simpleView.js"></script>
<!--<script src="js/backbone.paginator.js"></script>-->
</body>
</html>
I just can't get my head around this. The view is not rendered with the collection data. Please help!
I think it's because the fetch method on your collection is executed asynchronously and has therefore not completed when you create your view (if you look at the console I would expect the log statement in the success callback to display after the log statements underneath). This means that your view render method is called before the collection is populated and the reset event (which you're binding to in your view) is never triggered.
Try updating the code which instantiates everything as follows:
$(function(){
app.collections.CollectionItems = new app.collections.Directory();
//app.collections.CollectionItems.fetch();
//console.log(app.collections.CollectionItems.fetch());
app.collections.CollectionItems.fetch({
success: function (collection,response) {
console.log(response);
app.views.app = new app.views.masterView({collection: app.collections.CollectionItems});
}
});
});

How can I save a collection, or atleast a portion of it, in backbone.js

I need to maintain the order of models in a collection that are in a model and be able to save it to the server. I know I can save the individual models, but when I save the "parent model" that contains the collection the attribute holding the collection is now saved.
Is there a way to do this? Below is my code. And I know it probably isn't the best, I am still learning.
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery-ui.js"></script>
<script type="text/javascript" src="json2.js"></script>
<script type="text/javascript" src="underscore-min.js"></script>
<script type="text/javascript" src="backbone-min.js"></script>
<script type="text/javascript">
$(function() {
var WO = Backbone.Model.extend({
wonum: null,
part: null,
desc: null,
initialize: function()
{
this.url = '/rest/wo/'+this.get('wonum');
}
});
var WOView = Backbone.View.extend({
tagName: "tr",
className: "wo",
initialize: function(options)
{
this.render = _.bind(this.render, this);
},
render: function()
{
$(this.el).html("<td>"+this.model.get('wonum')+"</td><td>"+this.model.get('part')+"</td><td>"+this.model.get('desc')+"</td>");
return this;
}
});
var WOs = Backbone.Collection.extend({
model: WO,
url: '/rest/section/wos/'
});
var Section = Backbone.Model.extend({
defaults: {
name : "Section"
},
wos: [],
url: '/rest/section/',
initialize: function()
{
this.wos = new WOs();
this.wos.url += this.id;
this.url += this.id;
}
});
var SectionView = Backbone.View.extend({
tagName: "table",
initialize: function()
{
_(this).bindAll('add','remove');
var that = this;
this._woViews = [];
this.model.wos.each(this.add);
this.model.wos.bind('add', this.add);
},
add: function(woObj)
{
var wov = new WOView({
model: woObj,
id: woObj.get('wonum')});
this._woViews.push(wov);
if(this._rendered)
$(this.el).append(wov.render().el);
this.model.save();
},
render: function()
{
this._rendered = true;
var that = this;
$(this.el).empty();
$(this.el).append("<thead><th>WO</th><th>Part</th><th>Desc</th></thead>");
$(this.el).append("<tbody>");
_(this._woViews).each(function(wov)
{
$(that.el).append(wov.render().el);
});
$(this.el).append("</tbody>");
return this;
}
});
var sec = new Section({id: 1});
sec.wos.add({
wonum: 1001,
part: 'p1001',
desc: 'd1001'});
sec.wos.add({
wonum: 1002,
part: 'p1002',
desc: 'd1002'});
var secv = new SectionView({model: sec, id: sec.get('id')});
$("body").append(secv.render().el);
$("#addwo").bind("click",function()
{
secv.add(new WO({
wonum: 1005,
part: 'p1005',
desc: 'd1005'}));
});
});
</script>
</head>
<body>
<button id='addwo'>Add WO</button>
</body>
</html>
I would consider using the Collection's comparator function (which you can set) to preserve the order of the collection. This comparator would potentially use a property of the models; so for instance, the model's name or even a position property.
Using this approach, you would just save each model independently, but have the collection potentially refresh itself (where it would use the comparator to preserve the desired order).

Categories

Resources