I am trying to figure out if I can pass a variable to a template.
Here is the template:
<script type="text/template" id="modal-template">
<table class="table">
<thead>
<tr>
<th>Team Name</th>
</tr>
</thead>
<tbody>
<% for(var i=0; i
<XXX.length
; i++) { %>
<tr>
<td>
<a href='/users/<%=user._id%>/teams/<%= teams[i]._id%>/teamDashboard'>
<%= XXX[i].teamName %>
</a>
</td>
</tr>
<% } %>
</tbody>
</table>
</div>
</script>
I want to pass the above template a variable, let's say it's the variable identified above and below named XXX.
<script>
$(function($) {
var XXX = {};
//how can I pass the template the variable XXX???
var Modal = Backbone.Modal.extend({
template: _.template($('#modal-template').html()),
cancelEl: '.bbm-button'
});
$('.ImportTeamsFromTeamSnap').on('click', function(){
var modalView = new Modal();
$('.app').html(modalView.render().el);
});
});
</script>
Basically I want the template to render differently depending on the variable XXX. This could be a handlebars template, or any type of template that makes it possible.
Is this possible?
You can pass a Model to the modal. Something like this:
<script>
$(function($) {
var XXX = {};
//how can I pass the template the variable XXX???
var Modal = Backbone.Modal.extend({
template: _.template($('#modal-template').html()),
cancelEl: '.bbm-button'
});
$('.ImportTeamsFromTeamSnap').on('click', function(){
var MyModel = Backbone.Model.extends({});
var modalView = new Modal();
modalView.model = new MyModel(XXX);
$('.app').html(modalView.render().el);
});
});
</script>
Related
I am trying to develop my very first Tableau extension for Tableau server. I am developing it locally.
It is almost a Hello World kind of extension.
When I try to add an extension, it throws me an error "Request Rejected By Server"
It is a node.js app and running perfectly fine.
Here is my server.js
const express = require('express');
const app = express();
const process = require('process');
app.get('/', async function(req, res){
res.sendFile(__dirname + "/public/datasources.html");
});
const listener = app.listen(3030, () =>{
console.log("App is listening on port " + listener.address().port);
Here is my datasources.html.. This is one of those provided as sample from tableau.. I just added js part of it at the end. All in one file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Datasources Sample</title>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" ></script>
<!-- Extensions Library (this will be hosted on a CDN eventually) -->
<script src="https://extensions.tableauusercontent.com/resources/tableau.extensions.1.latest.min.js"></script>
<!-- Our extension's code -->
</head>
<body>
<div class="container">
<!-- DataSources Table -->
<div id="dataSources">
<h4>All DataSources</h4>
<div class="table-responsive">
<table id="loading" class="table">
<tbody><tr><td>Loading...</td></tr></tbody>
</table>
<table id="dataSourcesTable" class="table table-striped hidden">
<thead>
<tr>
<th>DataSource Name</th>
<th>Auto Refresh</th>
<th style="width: 100%">Info</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<!-- More dataSource info modal -->
<div class="modal fade" id="infoModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">DataSource Details</h4>
</div>
<div id="dataSourceDetails" class="modal-body">
<div class="table-responsive">
<table id="detailsTable" class="table">
<tbody>
<tr>
<td>DataSource Name</td>
<td id="nameDetail"></td>
</tr>
<tr>
<td>DataSource Id</td>
<td id="idDetail"></td>
</tr>
<tr>
<td>Type</td>
<td id="typeDetail"></td>
</tr>
<tr>
<td>Fields</td>
<td id="fieldsDetail"></td>
</tr>
<tr>
<td>Connections</td>
<td id="connectionsDetail"></td>
</tr>
<tr>
<td>Active Tables</td>
<td id="activeTablesDetail"></td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Wrap everything in an anonymous function to avoid polluting the global namespace
(function () {
$(document).ready(function () {
tableau.extensions.initializeAsync().then(function () {
// Since dataSource info is attached to the worksheet, we will perform
// one async call per worksheet to get every dataSource used in this
// dashboard. This demonstrates the use of Promise.all to combine
// promises together and wait for each of them to resolve.
let dataSourceFetchPromises = [];
// Maps dataSource id to dataSource so we can keep track of unique dataSources.
let dashboardDataSources = {};
// To get dataSource info, first get the dashboard.
const dashboard = tableau.extensions.dashboardContent.dashboard;
// Then loop through each worksheet and get its dataSources, save promise for later.
dashboard.worksheets.forEach(function (worksheet) {
dataSourceFetchPromises.push(worksheet.getDataSourcesAsync());
});
Promise.all(dataSourceFetchPromises).then(function (fetchResults) {
fetchResults.forEach(function (dataSourcesForWorksheet) {
dataSourcesForWorksheet.forEach(function (dataSource) {
if (!dashboardDataSources[dataSource.id]) { // We've already seen it, skip it.
dashboardDataSources[dataSource.id] = dataSource;
}
});
});
buildDataSourcesTable(dashboardDataSources);
// This just modifies the UI by removing the loading banner and showing the dataSources table.
$('#loading').addClass('hidden');
$('#dataSourcesTable').removeClass('hidden').addClass('show');
});
}, function (err) {
// Something went wrong in initialization.
console.log('Error while Initializing: ' + err.toString());
});
});
// Refreshes the given dataSource.
function refreshDataSource (dataSource) {
dataSource.refreshAsync().then(function () {
console.log(dataSource.name + ': Refreshed Successfully');
});
}
// Displays a modal dialog with more details about the given dataSource.
function showModal (dataSource) {
let modal = $('#infoModal');
$('#nameDetail').text(dataSource.name);
$('#idDetail').text(dataSource.id);
$('#typeDetail').text((dataSource.isExtract) ? 'Extract' : 'Live');
// Loop through every field in the dataSource and concat it to a string.
let fieldNamesStr = '';
dataSource.fields.forEach(function (field) {
fieldNamesStr += field.name + ', ';
});
// Slice off the last ", " for formatting.
$('#fieldsDetail').text(fieldNamesStr.slice(0, -2));
dataSource.getConnectionSummariesAsync().then(function (connectionSummaries) {
// Loop through each connection summary and list the connection's
// name and type in the info field
let connectionsStr = '';
connectionSummaries.forEach(function (summary) {
connectionsStr += summary.name + ': ' + summary.type + ', ';
});
// Slice of the last ", " for formatting.
$('#connectionsDetail').text(connectionsStr.slice(0, -2));
});
dataSource.getActiveTablesAsync().then(function (activeTables) {
// Loop through each table that was used in creating this datasource
let tableStr = '';
activeTables.forEach(function (table) {
tableStr += table.name + ', ';
});
// Slice of the last ", " for formatting.
$('#activeTablesDetail').text(tableStr.slice(0, -2));
});
modal.modal('show');
}
// Constructs UI that displays all the dataSources in this dashboard
// given a mapping from dataSourceId to dataSource objects.
function buildDataSourcesTable (dataSources) {
// Clear the table first.
$('#dataSourcesTable > tbody tr').remove();
const dataSourcesTable = $('#dataSourcesTable > tbody')[0];
// Add an entry to the dataSources table for each dataSource.
for (let dataSourceId in dataSources) {
const dataSource = dataSources[dataSourceId];
let newRow = dataSourcesTable.insertRow(dataSourcesTable.rows.length);
let nameCell = newRow.insertCell(0);
let refreshCell = newRow.insertCell(1);
let infoCell = newRow.insertCell(2);
let refreshButton = document.createElement('button');
refreshButton.innerHTML = ('Refresh Now');
refreshButton.type = 'button';
refreshButton.className = 'btn btn-primary';
refreshButton.addEventListener('click', function () { refreshDataSource(dataSource); });
let infoSpan = document.createElement('span');
infoSpan.className = 'glyphicon glyphicon-info-sign';
infoSpan.addEventListener('click', function () { showModal(dataSource); });
nameCell.innerHTML = dataSource.name;
refreshCell.appendChild(refreshButton);
infoCell.appendChild(infoSpan);
}
}
})();
</script>
</body>
</html>
And here is my trex extension file.
<?xml version="1.0" encoding="utf-8"?>
<manifest manifest-version="0.1" xmlns="http://www.tableau.com/xml/extension_manifest">
<dashboard-extension id="com.tableau.extensions.samples.datasources" extension-version="0.6.0">
<default-locale>en_US</default-locale>
<name resource-id="name"/>
<description>DataSources Sample</description>
<author name="tableau" email="github#tableau.com" organization="tableau" website="https://www.tableau.com"/>
<min-api-version>0.8</min-api-version>
<source-location>
<url>http://MACHINE_NAME:3030/</url>
</source-location>
<icon>iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAlhJREFUOI2Nkt9vy1EYh5/3bbsvRSySCZbIxI+ZCKsN2TKtSFyIrV2WuRCJuBiJWxfuxCVXbvwFgiEtposgLFJElnbU1SxIZIIRJDKTrdu+53Uhra4mce7Oe57Pcz7JOULFisViwZ+29LAzOSjQYDgz1ZcCvWuXV11MJpN+OS/lm6179teqH0yDqxPTCyKSA8DcDsyOmOprnCaeP7459pdgy969i0LTC3IO/RQMyoHcQN+3cnljW3dNIFC47qDaK3g7BwdTkwBaBELT4ZPOUVWgKl4ZBnjxJPUlMDnTDrp0pmr6RHFeEjjcUUXPDGeSEwDN0Xg8sivxMhJNjGzbHd8PkM3eHRfkrBM5NkcQaY2vUnTlrDIA0NoaX+KLXFFlowr14tvVpqb2MICzmQcKqxvbumv+NAhZGCCIPwEw6QWXKYRL/VUXO0+rAUJiPwAk5MIlgVfwPjjHLCL1APmHN94ZdqeYN+NW/mn6I4BvwQYchcLnwFhJMDiYmlRxAzjpKWZkYkUCcZ2I61wi37tLbYyjiN0fHk5Oz3nGSLSzBbNHCF35R7f6K1/hN9PRhek11FrymfQQQKB4+Gl05P2qNRtmETlXW7e+b2z01dfycGNbfFMAbqNyKp9Jp4rzOT8RYFs0njJkc2iqsCObvTsOsDWWqA5C1uFy+Uz/oXJeKwVT4h0RmPUXhi79vuC0Ku6yOffTK3g9lfxfDQAisY516sg5kfOCiJk7HoLt2cf9b/9LANAc7dznm98PagG1fUOZ9IP5uMB8Q4CPoyNvausapkTt3rNMuvdf3C/o6+czhtdwmwAAAABJRU5ErkJggg==</icon>
<permissions>
<permission>full data</permission>
</permissions>
</dashboard-extension>
<resources>
<resource id="name">
<text locale="en_US">DataSources Sample</text>
</resource>
</resources>
</manifest>
Do I have to do something on Tableau server side to make it work?
This might be because you are using http:// without localhost. That is not allowed. I'm not sure why the error message is so unhelpful, but it could be that the error coming back from server is not formatted well for the client error box. Hard to know without logs. :)
Try out either switching to hosting your extension from http://localhost or create a self-signed certificate with SAN, add that to your trust store and host from https:// instead.
I want to display data which is coming from database. In controller file I am getting array of objects and I am passing that array of objects to my ejs file. On my ejs file I am getting that "nameOfArray" is not defined.
Here is my controller file:
product.find().lean().exec((err, products) => {
if(err) {
return;
}
else {
let productsList = products;
res.render('admin/products', { data: productsList });
}
})
Here is product.ejs file:
<table>
<tbody>
<% data.forEach(function(product) { %>
<tr>
<td>
<%= product.productName %>
</td>
</tr>
<% }); %>
</tbody>
</table>
By running this it is showing that data is not defined.
I'm trying to build a project in nodejs as server and firebase as my realtime db and having some problems with forwarding the data to my html.
I getting the error:
Cannot set headers after they are sent to the client
on change
I'm trying to pass the updated arr to html but can't find a way to do that.
server.js:
const locksRef = await firebase.firebase.database().ref('locks')
let arr = []
//get list of locks
const t = locksRef.on('value', (data) => {
tempResult3 = data.val()
result3 = []
const numOfKeys = Object.keys(tempResult3)
numOfKeys.forEach((x) => {
result3.push(tempResult3[x])
})
result3.forEach((k) => {
myLocks.forEach((my) => {
if (k.id == my) {
arr.push(k)
}
})
})
res.render('ListOfLocks', { arr })
})
html
<body>
<h1>ListOfHouses</h1>
<table border="1px solid black">
<thead>
<th>Name And Address</th>
</thead>
<tbody>
{{#each arr}}
<tr>
<td id="data"> {{name}} - {{address}}</td>
<td>
<form action="/seekKeys" method="post"><button name="{{locks}}" type="submit">LookForKey</button>
</form>
</td>
</tr>
{{/each}}
</tbody>
</table>
</body>
I am looking for a solution for my EJS template. I am working on a project and I have completed about 50% of it. Currently I am working on a web page where I have to display the SQL data into EJS web template.
I have posted my coding which is i am working on it.
data is receiving from database (I checked with console.log and I posted the Json out put).
I tried all the possible ways to work it out but I did not get the result. It would be great if someone could help me..
Thanks in advance.
/* app.js */
app.get('/data', receiveData);
function receiveData(req, res)
{
db.executeSql("SELECT * FROM arduino", function (recordsets, err, ) {
var data = JSON.stringify(recordsets);
if (err) {
httpMsgs.show500(request, res, err);
}
else {
var Jdata = JSON.parse(data);
res.render('arduino',{Jdata:Jdata});
console.log(data);
}
});
}
/* arduino.ejs */
<html>
<head>
<body>
<div class="page-data">
<div class="data-table">
<table border="1" cellpadding="7" cellspacing="7">
<tr>
<th> - </th>
<th>ID</th>
<th>Machine</th>
<th>Start Time</th>
<th>End Time</th>
<th>Length Time</th>
<th> Day/Night</th>
<th>Job Number</th>
</tr>
<% if(Jdata.length){
for(var i = 0;i < Jdata.length;i++) { %>
<tr>
<td><%=(i+1)%></td>
<td> </td>
<td><%=Jdata[i].Machine%></td>
<td><%=Jdata[i].StartTime%></td>
<td><%=Jdata[i].EndTime%></td>
<td><%=Jdata[i].LengthTime%></td>
<td><%=Jdata[i].Day%></td>
<td><%=Jdata[i].ID %></td>
<td><%=Jdata[i].JobNumber %></td>
</tr>
<% }
}else{ %>
<tr>
<td colspan="3">No Data</td>
</tr>
<% } %>
</table>
</div>
</div>
</body>
</head>
</html>
{"recordsets":[[{"ID":1,"Machine":"TRUMPF 5000","StartTime":"2018-11-01T15:28:51.000Z","EndTime":"2018-11-01T15:52:11.000Z","LengthTime":271,"Day":"Day","JobNumber":null}]]
I'm trying to iterate with Blaze over dynamically created object. I have the collection and the object, but I can't display the data in my tables and I don't understand why.
Here's my code to retrieve the object :
In my Template Helpers :
fields: ()=> {
var collectionSelected = FlowRouter.current().params.collectionName;
// var data = Mongo.Collection.get(collectionSelected).find().count();
var collectionObject = Collections.findOne({name: collectionSelected});
console.log(Collections.findOne({name: collectionSelected}));
return Collections.findOne({name: collectionSelected});
},
values: ()=> {
var collectionSelected = FlowRouter.getParam('collectionName');
var collectionObject = Collections.findOne({name: collectionSelected});
var dataArray = [];
var data = Meteor.call('findElmt', collectionSelected, function(err, res){
console.log('VALUES : ');
console.log(res);
return res;
});
},
The findElmt method :
findElmt(collectionName){
if (global.hasOwnProperty(collectionName)){
var res = Mongo.Collection.get(collectionName).find().fetch();
console.log(res);
return res;
}
else {
global[collectionName] = new Meteor.Collection(collectionName);
var res = Mongo.Collection.get(collectionName).find().fetch();
console.log(res);
return res;
}
}
And finally the way I'm trying to display it with Blaze :
<table data-toggle="table" data-show-columns="true" data-search="true" data-pagination="true">
{{#with fields}}
{{#if Template.subscriptionsReady}}
<thead>
<tr>
{{#each fields.fieldsName}}
<th data-sortable="true">{{this}}</th>
{{/each}}
</tr>
</thead>
{{else}}
<p>Loading...</p>
{{/if}}
{{/with}}
<tbody>
{{#each values}}
<tr>
{{#each valueString in values.items}}
<td>{{valueString}}</td>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
If you have any advice on what I'm doing wrong, thank you !
EDIT 1 : I added the fields helper !
Supposing that values is an array of JsonObject with the field items, you are iterating the wrong way.
When using {{#each}} and not {{#each in}} you can access directly your properties with itemsor with this.items.
If values is an array of JsonObject :
<tbody>
{{#each values}}
<tr>
{{#each valueString in this.items}} // values.items -> this.items
<td>{{valueString}}</td>
{{/each}}
</tr>
{{/each}}
</tbody>
If values is a JsonObject, you can use with :
<tbody>
{{#with values}}
<tr>
{{#each valueString in this.items}} // values.items -> this.items
<td>{{valueString}}</td>
{{/each}}
</tr>
{{/with}}
</tbody>
Then to have a reactive returned value with Method call you can use the following package :
https://atmospherejs.com/simple/reactive-method
Thank you a lot for your help, I finally nailed it.
Here's the final code for the future lost soul like me !
Template Helpers :
fields: ()=> {
var collectionSelected = FlowRouter.current().params.collectionName;
// var data = Mongo.Collection.get(collectionSelected).find().count();
var collectionObject = Collections.findOne({name: collectionSelected});
console.log(Collections.findOne({name: collectionSelected}));
return Collections.findOne({name: collectionSelected});
},
values: ()=> {
var collectionSelected = FlowRouter.getParam('collectionName');
var collectionObject = Collections.findOne({name: collectionSelected});
var dataArray = [];
console.log(ReactiveMethod.call("findElmt", collectionSelected));
return ReactiveMethod.call("findElmt", collectionSelected);
}
The server side FindElmt method didn't change,
and finally the Blaze code :
<table data-toggle="table" data-show-columns="true" data-search="true" data-pagination="true">
{{#with fields}}
{{#if Template.subscriptionsReady}}
<thead>
<tr>
{{#each fields.fieldsName}}
<th data-sortable="true">{{this}}</th>
{{else}}
{{! will this fix this issue? }}
{{/each}}
</tr>
</thead>
{{else}}
<p>Loading...</p>
{{/if}}
{{else}}
{{! will this fix this issue? }}
{{/with}}
{{#with values}}
<tbody>
{{#each values}}
<tr>
{{#each valueString in this.items}}
<td>{{valueString}}</td>
{{else}}
{{! will this fix this issue? }}
{{/each}}
</tr>
{{else}}
{{! will this fix this issue? }}
{{/each}}
</tbody>
{{else}}
{{! will this fix this issue? }}
{{/with}}
</table>