I am working on a code gen tool, and I am using Lodash to template the output files. When I try running the resultant function from _.template(XXX) I get
"AppData" (the name of the template variable) is not defined.
I have tried to call temp below with and without the AppData variable and both give me
"ReferenceError: AppData is not defined"
templates.forEach((template) => {
let temp = _.template(template, { AppData: AppData });
output = temp(AppData);
});
This is the AppData object:
let AppData = { clientId: clientId,
appId: applicationId,
intents: ['Testing1',
'Testing2',
'Testing3',
'Testing4'
]};
Here is one of the 3 templates:
<% _.each(AppData.intents, function( intent ){ %>
<transition event="<%=intent%>" target="<%=intent%>">
<state id="<%=intent%>">
<onentry>
<assign location="href_answer" expr="tfs.getKBAPIUrl(DNIS, environment, '<%=intent%>')"/>
<assign location="reason" expr="'<%=intent%>'"/>
<script><![CDATA[presentAnswer(href_answer,reason);]]></script>
</onentry>
</state>
<% }) %>
Stack is not letting me post the output, but it's the function representing the finished template.
Perhaps you should step back and get the lodash to first do the templating first and then once you get the templating work, then introduce more complexity...
var tfsStr = document.querySelector('#tfs-template').textContent;
var compiled = _.template(tfsStr, {
intents: AppData.intents,
_: _
});
I did a little codepen to test the templating
After much head smashing, I realized a simple issue.
I was passing the object incorrectly, and the templates were looking for the wrong thing. In the templates I removed my AppData. object notation and updated the code to look like this. The templates picked up the values correctly.
templates.forEach((template) => {
let temp = _.template(template);
output += temp(AppData);
});
A bit of a rookie mistake, first time using Lodash.
Related
Given the following localStorage code (jsfiddle) :
// my new information
var data = {character: "中", totalMistakes: 0};
var han = data.character;
// create localStorage; Unpack, update, repackage knol
/* **** THIS IS THE SECTION TO CONVERT **** */
localStorage.knol = '{}'; // create pseudo object, as string
var knol = JSON.parse(localStorage.knol)
knol[han] = data;
localStorage.knol = JSON.stringify(knol);
// Print to check if all went well.
console.log('data: ',data)
console.log('han: ',han)
console.log('knol: ',knol)
console.log('localStorage.knol: ',localStorage.knol)
console.log('localStorage.knol: ',JSON.parse(localStorage.knol))
console.log('localStorage.knol[han]: ',JSON.parse(localStorage.knol)[han])
At the end, localStorage.knol is :
{
"中": {character: "中", totalMistakes: 0}
}
I'am looking for a Mongo-like js library to store data on client side indexedDB, with a syntax similar to MongoDB with which I'am already familiar.
How to convert localStorage code above into Mongo-like IndexedDB library syntax so to store an object ?
EDIT: I suggest minimongo, but any MongoDB-like library storing in indexedDB will do.
There is a variety of librairies available to do that.
Dexie.js
Using Dexie.js and its API (jsfiddle) :
<!-- Include dexie.js -->
<script src="https://unpkg.com/dexie#latest/dist/dexie.js"></script>
<script>
var db = new Dexie('MyDatabase');
// Define a schema
db.version(1).stores({ knol: 'character, totalMistakes' });
// Open the database
db.open().catch(function(error) { alert('Uh oh : ' + error); });
// or make a new one
db.knol.put({ character: '中', totalMistakes: 8 });
// Find some old friends
var mistakes = db.knol.where('totalMistakes');
//mistakes.above(6).each (function (item) { console.log (item); });
mistakes.aboveOrEqual(0).each (function (item) { console.log (item)});
</script>
Minimongo
I don't recommend it, but there is how to use it in web browsers
ZangoDB
(Exploration ongoing https://jsfiddle.net/vb92pecv/3/ )
I can't solve this for almost four hours, and i can't find any helpful documentation for this kind of problems. This is the issue, I'm using pug/jade templates and i want to call function inside pug template to transform some data
This is the main template:
/** main template */
section
each pet in pets
.pet
.photo-column
img(src= pet.photo)
.info-column
h2= pet.name
span.species= (pet.species)
p Age: #{calculateAge(pet.birthYear)} //here I need to call calculateAge function
if pet.favFoods
h4.headline-bar Favorite Foods
ul.favorite-foods
each favFood in pet.favFoods
li!= favFood
/** end main template **/
This is the external function:
/** calculateAge.js **/
module.exports = function(birthYear) {
var age = new Date().getFullYear() - birthYear;
if (age > 0) {
return age + " years old";
} else {
return "Less than a year old";
}
};
/** end calculateAge.js **/
What shell I do to make this happen?
There may be better way to handle this, but I usually do it by importing the external module and then passing it as part of template context object. That means the code that renders the template should be something like:
const calculateAge = require("calculateAge"); // change path accordingly
router.get("/main", function(){
let pageInfo = {};
pageInfo.title = "Demo";
pageInfo.calculateAge = calculateAge;
res.render("main", pageInfo);
});
Now, you can access calculateAge in your template. If this module is used a lot in most of the templates, then you should pass it as part of res.locals or app.locals so that it is available for all templates without the need to append it for every path request.
In PUG options use locals property to import functions you want to use inside your templates.
const calculateAge = require('./calculate-age');
const config = {
pug: {
locals: {
calculateAge,
},
},
};
Then you can use it in all your templates like this (please note the extra unescaping tag !{}):
p Age: !{calculateAge(pet.birthYear)}
Like in raw HTML if you want JS to execute in a sepcific part you need a script tag to enclose the js you want to use.
span.species= (pet.species)
p Age:
.script
calculateAge(pet.birthYear)
if pet.favFoods
Make your function available in pug like this:
//assuming you're using express
app.set('view engine', 'pug');
app.locals.someFunction = input => input * 5;
// or
import {someOtherFunction} from "packageOrFile";
app.locals.someOtherFunction = someOtherFunction;
In your pug you then can do
span= someFunction(10)
span= someOtherFunction(123)
This is basically what mahish wrote in his comment, but it actually answers the question satisfactory and here's the documentation.
You can write javascript with .script tag
script.
$( document ).ready(function() {
calculateAge(params)
})
I'm following the Progressive Web App lab from Google and it says that it's using localStorage for simplicity but that we should change it to idb.
Basically, we want to store a list of cities to display their weather information.
I tried using plain idb following the info here but I think I'm too new to this and I couldn't get any of this. Am I supposed to do:
const dbPromise = idb.open('keyval-store', 1, upgradeDB => {
upgradeDB.createObjectStore('keyval');
});
and would keyval be the name of my variable where I would use keyval.get() or keyval.set() to get and store values?
I decided to move on to the simpler idbKeyval, I'm doing:
app.saveSelectedCities = function() {
var selectedCities = JSON.stringify(app.selectedCities);
idbKeyval.set(selectedCities);
};
instead of the localStorage example:
app.saveSelectedCities = function() {
var selectedCities = JSON.stringify(app.selectedCities);
localStorage.selectedCities = selectedCities;
};
and
app.selectedCities = idbKeyval.keys().then(keys => console.log(keys)).catch(err => console.log('It failed!', err));
instead of the localStorage example:
app.selectedCities = localStorage.selectedCities;
But my app is not loading any data, and in the developer tools console, I get:
app.js:314 Uncaught ReferenceError: idbKeyval is not defined(…)
I'm sure I'm missing something trivial but these are my first steps with javascript and the likes, so please, any help with any of the points touched here would be greatly appreciated!
Given the error you're seeing, it looks like you've forgotten to include the idb-keyval library.
I too was going through this, and wanted it to work with localForage. Took a bit, because I'm new to it too, but here is what I used for the save and load functions which made it all work.
// TODO add saveSelectedCities function here
// Save list of cities to localStorage
app.saveSelectedCities = function() {
var selectedCities = JSON.stringify(app.selectedCities);
localforage.setItem('selectedCities', selectedCities);
//localStorage.selectedCities = selectedCities;
}
localforage.getItem('selectedCities').then(function(cityList) {
app.selectedCities = cityList;
app.selectedCities.forEach(function(city) {
app.getForecast(city.key, city.label);
});
}).catch(function(err) {
app.updateForecastCard(initialWeatherForecast);
app.selectedCities = [
{key: initialWeatherForecast.key, label: initialWeatherForecast.label}
];
app.saveSelectedCities();
});
I'm using Handlebars with Node, and that works fine:
require('handlebars');
var template = require('./templates/test-template.handlebars');
var markup = template({ 'some': 'data' });
console.log(markup);
That works fine. However, I need to register and use a custom helper in my template. So, now my code looks like this:
var Handlebars = require('handlebars');
Handlebars.registerHelper('ifEqual', function(attribute, value) {
if (attribute == value) {
return options.fn(this);
}
else {
return options.inverse(this);
}
});
var template = require('./templates/test-template.handlebars');
var markup = template({ 'some': 'data' });
console.log(markup);
But now when I run my script, I get
Error: Missing helper: 'ifEqual'
So: how can I define and use a custom helper in Node?
I figured it out. I needed to do this:
var Handlebars = require('handlebars/runtime')['default'];
One what's really cool is, this even works in the browser with Browserify.
However, I found that an even better way (and probably the "correct" way) is to precompile Handlebars templates via (shell command):
handlebars ./templates/ -c handlebars -f templates.js
Then I do this:
var Handlebars = require('handlebars');
require('./templates');
require('./helpers/logic');
module.exports.something = function() {
...
template = Handlebars.templates['template_name_here'];
...
};
Here is the way i did it.
I guess nowadays its a bit different.
const Handlebars = require('handlebars');
module.exports = function(){
Handlebars.registerHelper('stringify', function(stuff) {
return JSON.stringify(stuff);
});
};
then i made a little script to call require on all the helpers just so they get ran.
// Helpers Builder
let helpersPath = Path.join(__dirname, 'helpers');
fs.readdir(helpersPath, (err, files) => {
if (err) {throw err;}
files.filter((f) => {
return !!~f.indexOf('.js');
}).forEach((jsf) => {
require(Path.join(helpersPath, jsf))();
});
});
OR the simple way
require('./helpers/stringify')();
in fact you dont even have to export it as a function you can just not export anything at all and just call require from another js file with out the function params at the end.
I need to get a template from Ember.TEMPLATES, compile it with a specified object and get its raw HTML value.
Ember.TEMPLATES content (generated using gruntjs) returns a function and seems to be already passed through Handlebars.template() function so for example I would have this:
Ember.TEMPLATES["test"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {};
var buffer = '', hashTypes, hashContexts, escapeExpression=this.escapeExpression;
data.buffer.push("<strong>hello world ");
hashTypes = {};
hashContexts = {};
data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "test", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data})));
data.buffer.push("</strong>\n");
return buffer;
});
and would like to compile that template with new values from a JSON object.
I tried something like that based on what I've seen in Ember code:
var test = Ember.TEMPLATES['test'];
var compiled = test({ test: 'value' });
I thought it might work but it doesn't actually.
Basically I'd like to do like with standard handlebars :
Handlebars.compile('<strong>{{hello}}</strong>', { hello: 'world' });
Is there any way to compile a template with specified values, and get the HTML result using Emberjs?
Ember do some modifications in handlebars compiler to enable the use of computed properties, make templates update when model changes etc.
If you see the view render method, it does more than template(context), it use the context and some private custom data. So Handlebars.compile is diferent of Ember.Handlebars.compile and I think that compiled templates from Ember.Handlebars.compile, is not intended to be used outside of a Ember.View.
Marking script types with text/x-raw-handlebars, instead of text/x-handlebars make the template be compiled with Handlebars.compile.
The following sample will work, but without the ember features:
Template
<script type="text/x-raw-handlebars" data-template-name="custom-template">
First name: {{firstName}} <br/>Last name: {{lastName}}
</script>
Javascript
App = Ember.Application.create({
ready: function() {
var template = Ember.TEMPLATES['custom-template'];
var html = template({ firstName: 'Tom', lastName: 'Dale' });
$('body').append(html);
}
});
You can see this sample here http://jsfiddle.net/marciojunior/MC8QB/