Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Importing Jet Template does not bring Variables #107

Open
JesseRyan opened this issue Oct 17, 2018 · 10 comments
Open

Importing Jet Template does not bring Variables #107

JesseRyan opened this issue Oct 17, 2018 · 10 comments

Comments

@JesseRyan
Copy link

JesseRyan commented Oct 17, 2018

Consider the following:

Params.jet ->
{{ param1 := 1 }}
{{ param2 := 2 }}
{{ param3 := 3 }}
{{ param4 := 4 }}

then import Params.jet in another template.

SomeJetTemplate.jet ->
{{ import "Params.jet" }}
{{ "This is a string needing to use parameters : " + param1 }}

This throws a block level scope failure that param1 does not exist in the scope of the block...
Is there a way to load parameter configurations like this into other jet templates? Seems like this should work...

I do of course understand that parameters can be added to vars and imported into templates from compiled go code. However, we would like to remain dynamic and maintain the essence of Jet templates in that we could change the text i.e. the parameters on the fly without having to recompile go code.

@annismckenzie
Copy link
Member

annismckenzie commented Oct 17, 2018 via email

@annismckenzie
Copy link
Member

Did that help?

@JesseRyan
Copy link
Author

Hey thank you for attention again,

Unfortunately this did not work. Is this intended to work?
Perhaps I need to test this in a block for evaluation? Right now its just included in the template.

Do you have a working example? It would be really great if this would work.
JET is already heroic by the way.

@voidhaze
Copy link

having the same issue, +1 for feature request.

@voidhaze
Copy link

found a work around; {{ var = value }} seems to declare with global scope

@mchampaneri
Copy link

mchampaneri commented Aug 4, 2019

You have to pass data as third parameter like this,

 {{ include "Params.jet" .  }} // Here '.' means value of data passed to scope
 {{ include "Params.jet" [some variable]  }} // Here '.' means value of data passed to scope

Example,

Main Html Template
https://github.com/mchampaneri/MarchCMS/blob/master/themes/shortshot/pages/main.html

Partial Template
https://github.com/mchampaneri/MarchCMS/blob/master/themes/shortshot/pages/partials/singlePost.html

@mchampaneri
Copy link

found a work around; {{ var = value }} seems to declare with global scope

You don't need to declare in global scope.

@sauerbraten
Copy link
Collaborator

sauerbraten commented Jul 1, 2020

found a work around; {{ var = value }} seems to declare with global scope

That was actually a bug and fixed in 16fe512, so this won't work as a "workaround" anymore.

I'll look into importing variables as well was blocks, but I'm not sure it's something you'd want. Would you expect a variable "foo" from an imported template to overwrite a variable "foo" in your current template scope?

@jan-herout
Copy link
Contributor

@sauerbraten actually, in some cases this would be quite handy. Imagine you have set of templates that should be able to derive the same set of variables/attributes from what was provided to them.

For example:

  • let's asume you use jet to generate source codes for data warehouse transformations
  • let's assume that you have groups of databases serviced by different "ETL engines"
  • let's assume that you do not want to hardcode logic into the generating application

In this situation, it would be most useful to be able to include a template which contains the common logic and provides metadata to other templates. Imagine it as a subroutine.

Workaround:

  • in my solution I use a custom function which creates a map[string]string, included template stores metadata into it, and this allows the "parent" template reuse them.

This solution is "good from far", but far from good, I am afraid. But in my case it works.

Please note that I am posting this only to show that the case for this functionality is probably there, not to offer any solution.
For my case, it would be best if this was provided "out of the box", but I am afraid my knowledge of Jet internals is insufficcient for such a task.

Example use case

Please not that the example uses custom delimiters.

Consumer of the "common" logic

// include "globals"
<%- include "../COMMON/trf_commons.jet" map("database", o.GetTable().Database) %>

// later in the template .... access metadata prepared by trf_commons.jet
<%- pmrootdir := stashGet("pmRootDir")  %>

Provider of the "common" logic" (trf_commons.jet)

PLease note that this is a contrived and incomplete example. But it shows the idea.

<%- stashReset(false) %>
<%- database  := upper(.["database"])      %>
<%- if 
        database == "EP_MREP"       
     || database == "EP_MREP_WRK"
     || database == "EP_MREPADJ"
     || database == "EP_IPTV"
     || database == "EP_IPTV_WRK"           %>
     <%- engineId   = "21"                  %>
     <%- pmRootDir  = "PMRootDir_E21"       %>
     <%- streamINITName  = "START_021"      %>
     <%- streamFINALName = "FINAL_021"      %>
     <%- jobCategory     = "COMMAND_E21"    %>
<% end %>

<%- stashSet("engineId",     engineId)   %>
<%- stashSet("pmRootDir",    pmRootDir)  %>
<%- stashSet("auditRunID",   auditRunID) %>
<%- stashSet("pdc.streamINITName" , streamINITName  )  %>
<%- stashSet("pdc.streamFINALName", streamFINALName )  %>
<%- stashSet("pdc.jobCategory"    , jobCategory     )  %>

Snippet of code

// stashReset creates an empty global stash. The global stash is mutex protected map[string]string, which can
// later on be accessed via stashSet and stashGet functions.
// The function takes one oprional parameter. If the value provided is string "true", then stashGet WILL panic
// if you attempt to access key which was not yet stored using stashSet.
func stashReset(a jet.Arguments) reflect.Value {
	a.RequireNumOfArguments("stashReset", 0, 1)
	canPanic := strings.ToLower(jetGetParam(a, 0)) == "true"
	globalStash.m.Lock()
	globalStash.stash = make(map[string]string)
	globalStash.canPanic = canPanic
	globalStash.m.Unlock()
	return reflect.ValueOf("")
}

// stashSet stores a string value in the stash, and returns an empty string.
func stashSet(a jet.Arguments) reflect.Value {
	a.RequireNumOfArguments("stashSet", 2, 2)
	key := jetGetParam(a, 0)
	val := jetGetParam(a, 1)
	globalStash.m.Lock()
	globalStash.stash[key] = val
	globalStash.m.Unlock()
	return reflect.ValueOf("")
}

// stashGet retrieves string from global stash.
func stashGet(a jet.Arguments) reflect.Value {
	a.RequireNumOfArguments("stashGet", 1, 1)
	key := jetGetParam(a, 0)
	globalStash.m.Lock()
	val, ok := globalStash.stash[key]
	globalStash.m.Unlock()
	if !ok {
		if globalStash.canPanic {
			a.Panicf("stashGet: key not in stash: %s", key)
		}
	}
	r := reflect.ValueOf(val)
	return r
}

@sauerbraten
Copy link
Collaborator

sauerbraten commented Jul 13, 2021

It sounds like you could use extends for your use case: https://github.com/CloudyKit/jet/blob/master/docs/syntax.md#extends

Have a base template defining all the "global" vars you want, then make different "consuming" templates that extend from it. Since code outside of blocks doesn't run in the "consumer" (extending) templates, you'd have to define something like a main block and yield that in the base, as described in the docs.

Would this not solve the problem you're having?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants