hygen icon indicating copy to clipboard operation
hygen copied to clipboard

How to load local variables from JSON?

Open mk48 opened this issue 6 years ago • 7 comments

Thanks for the great library.

I can read variable values from CLI argument or prompt parameter. But I have lots of variables, so I have to keep in a separate JSON file.

Is there any way to load/read that JSON file and pass as local variables to the templates?

mk48 avatar Apr 01 '19 11:04 mk48

add an index.js file in your _templates/<your generator>/<your action use something like this untested code. pass --json path/of/file

// _templates/<generator>/<action>/index.js
const fs = require('fs')

module.exports = {
  params: ({ args }) => {
    let jsonData = {}
    if (args.json) {
      let rawdata = fs.readFileSync(args.json);
      jsonData = JSON.parse(rawdata);
    }
    return {
      ...args,
      ...jsonData
    }
  },
}

anithri avatar Apr 03 '19 20:04 anithri

I have added your code in my index.js and put that in my action directory. Now how can I access that json? in the template file when I put variable json, I get the path in the generated file, not the contents of the json. Did I do something wrong?

mahdinba97 avatar Jul 07 '19 06:07 mahdinba97

The return value of the params function get added to the template as variables. if the json above looks like {"color": "white","background":"purple"} and is exported as above, then in your template you can <%= color %> and <%= background %>

Another point of confusion may be the spread operator ...jsonData That adds all of the key value pairs to the object being returned. If it were returned as

return {
  ...args,
  jsonData,
}

You'd use it like <%= jsonData.color %>.

Also, args is everything you passed in via the command line. hygen jg page --name PinkFloyd --container band --route '/bands/pink_floyd' args = {name: 'PinkFloyd', container: 'band', route: '/bands/pink_floyd'}`

anithri avatar Jul 09 '19 16:07 anithri

I'm interested in the same thing but I'm fairly certain my code in index.js isn't running. (I've tried the suggested code. Logging consoles, throwing errors, etc..)

cmd: hygen StackEntity new Catalog prompt: favorite color: blahhhh result: Loaded templates: xxx\Frontend_templates ReferenceError: ejs:7 5| 6| //endpoint calls go here

7| <%=jsonData.color%> 8| <%=jsonData.background%> 9| } 10|

jsonData is not defined Hygen v4.0.11

File structure is below.

Capture

orionjensen avatar Oct 09 '19 15:10 orionjensen

add an index.js file in your _templates/<your generator>/<your action use something like this untested code. pass --json path/of/file

// _templates/<generator>/<action>/index.js
const fs = require('fs')

module.exports = {
  params: ({ args }) => {
    let jsonData = {}
    if (args.json) {
      let rawdata = fs.readFileSync(args.json);
      jsonData = JSON.parse(rawdata);
    }
    return {
      ...args,
      ...jsonData
    }
  },
}

but prompt doesn't work

YuunYang avatar Nov 15 '19 07:11 YuunYang

Is there any workaround for this?

Warkanlock avatar Apr 24 '21 12:04 Warkanlock

I found a simplier, uglier but still acceptable workaround for this: I use the initial property of prompt.js to pass more complex json data, so you can access the data in your template playing with JSON.parse() and JSON.stringify():

For example in my prompt.js I write the following JSON (non-sense, just for the show):

// prompt.js
module.exports = [
{
    type: "input",
    name: "filename",
    message: "Type file name:",
}
{
    type: "input",
    name: "modelStr",
    message: "This is the json data you wanna pass, just confirm:",
    initial: `[
			{ "label": "title", "id": 1, "fr": "titre", "required": true },
			{ "label": "order", "id": 2, "fr": "ordre", "required": false },
			{ "label": "link", "id": 3, "fr": "lien", "required": true }
		]`
  }

then in my template:

// mytemplate.ejs.t
---
to: <%= filename %>.js
---
// this will build a proper array from the input string 
<% model = JSON.parse(modelStr) %>

// Then I can loop on my array to properly build my file as I want,
// In the example below; NOTE THAT I USE "<%-" INSTEAD OF <%=" so
// I can display strings with quotes or double quotes (otherwise I got  strings like #&32.
// Since from json input we always need quotes for strings, note how I remove 
// them when needed with .replace(/"/g, "")
const myObject = {
<% for (let i=0; i<model2.length; i++) { let item = model2[i]%>
<%-JSON.stringify(item.label).replace(/"/g, "")%> : { id : <%-JSON.stringify(item.id)%>, fr: <%-JSON.stringify(item.fr)%>, required: <%-JSON.stringify(item.required)%> },
<% } %>
}

Output will be:

const myObject = {
  title : { id : 1, fr: "titre", required: true },
  order : { id : 2, fr: "ordre", required: false },
  link : { id : 3, fr: "lien", required: true },
}

At least, you can pass as much json data this way by additionning more inputs to the promps.js

tperrinweembi avatar May 30 '23 09:05 tperrinweembi