stencilproject/Stencil

Custom tag's render method not being called when using inheritance

bfad opened this issue · 3 comments

bfad commented

Here is my swift code:

class SetVarNode: NodeType {
  let newVariable: String
  let value: Resolvable

  static func parse(_ parser: TokenParser, token: Token) throws -> NodeType {
    let components = token.components()
    guard components.count == 4 && components[2] == "to" else {
      throw TemplateSyntaxError("'set' statements should use the following 'set x to y' `\(token.contents)`.")
    }

    let newVariable = components[1].trimmingCharacters(in: CharacterSet.whitespaces)
    let value = try parser.compileFilter(components[3])

    return SetVarNode(newVariable: newVariable, value: value)
  }

  init(newVariable: String, value: Resolvable) {
    self.newVariable = newVariable
    self.value = value
  }

  func render(_ context: Context) throws -> String {
    print("here")
    let resolved = try value.resolve(context)

    context[newVariable] = resolved
    return ""
  }
}

When I use it in a template with inheritance, it does call parse and initialize the tag, but it never calls render:

base.html

<html>
 <body>{% block body %}{% endblock %}</body>
</html>

template.html

{% extends "base.html" %}
{% set about to my_var %}
{% block body %}here{{my_var}}{% endblock %}

If I remove the "extends" tag to get rid of inheritance, I see that render is called because "here" is printed out just as I would expect.

bfad commented

One further thing I discovered is that if I move my custom tag inside one of the blocks, then render is called on it.

kylef commented

@bfad I think the reason for this is that your set block is not placed inside a block inside an extend. Remember, that any area outside of a block in an extend is not rendered, by design.

So instead of the following:

{% extends "base.html" %}
{% set about to my_var %}
{% block body %}here{{my_var}}{% endblock %}

You should use:

{% extends "base.html" %}

{% block body %}
{% set about to my_var %}
here{{my_var}}
{% endblock %}
bfad commented

@kylef you were right. I was hoping not to have to use the tag for each block, but I can get that effect by placing it above the extends tag. Thanks for the insight.