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

Local variable API refinement #371

Closed
sunng87 opened this issue Aug 9, 2020 · 9 comments · Fixed by #372
Closed

Local variable API refinement #371

sunng87 opened this issue Aug 9, 2020 · 9 comments · Fixed by #372
Milestone

Comments

@sunng87
Copy link
Owner

sunng87 commented Aug 9, 2020

  1. Keep the get/set API consistent with @ prefix
  2. Use &str where possible
@tmpfs
Copy link

tmpfs commented Aug 16, 2020

I just noticed this and a couple of times would have liked to set custom local variables using the @ prefix but have been unable to do it. Would you consider exposing an API specifically for this purpose? It would be useful to prevent potential naming collisions when iterating in helpers and accepting user-defined arbitrary fields.

If this is already possible would love to know how to do it, thanks!

@sunng87
Copy link
Owner Author

sunng87 commented Aug 16, 2020

This is possible. The local variable is associated with current block (for example, #each and #with yields a block) . To access local variable in parent block you can use @../name.

Check the source of each block for detail. By the way, this API is going to change in #372 and 4.0. The @ is no longer needed.

@tmpfs
Copy link

tmpfs commented Aug 16, 2020

Ah, thanks! My mistake was not creating a block for my helper iterator. If i create the block i can use set_local_var(), awesome 👍

@sunng87
Copy link
Owner Author

sunng87 commented Aug 16, 2020

Yes. I suggest you to check the implementation of each block for your custom block. Let me know if you have any question for it.

The handlebars book #368 was in my backlog. I will cover more detail of helper development in the doc.

@tmpfs
Copy link

tmpfs commented Sep 14, 2020

Thanks so much for the advice @sunng87, after some study I found set_base_value() in conjunction with set_local_var() to be what I needed 👍

@cryarchy
Copy link

I have tried understanding and reproducing in part the implementations for both #each and #with to implement my own block helper. I am, however, unable to access the parent scope from within my block helper using either @../parentVariable and ../parentVariable. Do I have to explicitly pass in the parent blocks? If yes, how is that achieved. Please help.

@sunng87
Copy link
Owner Author

sunng87 commented Feb 19, 2021

@cryarchy @../parentVariable is the right syntax. Please make sure you have created a block for your current helper.

Do you have a link for your current implementation?

@cryarchy
Copy link

cryarchy commented Feb 20, 2021

I have tried the @../parentVariable with no success. Here is my helper's implementation.

use handlebars::{
  BlockContext, Context, Handlebars, Helper, HelperResult, Output, RenderContext, RenderError,
  Renderable,
};

pub fn handler<'reg, 'rc>(
  h: &Helper<'reg, 'rc>,
  handle: &'reg Handlebars,
  ctx: &'rc Context,
  render_ctx: &mut RenderContext<'reg, 'rc>,
  out: &mut dyn Output,
) -> HelperResult {
  let lhs = h
    .param(0)
    .map(|v| v.value())
    .ok_or(RenderError::new("expected a left hand side operand"))?
    .as_str()
    .ok_or(RenderError::new(
      "expected the left hand side operand to be a string",
    ))?;
  let rhs = h
    .hash()
    .get("map")
    .map(|v| v.value())
    .ok_or(RenderError::new("expected a 'map' hash argument"))?;
  if let Some(val) = rhs.get(lhs) {
    if let Some(template) = h.template() {
      let mut new_block = BlockContext::new();
      new_block.set_base_value(val.to_owned());
      render_ctx.push_block(new_block);
      template.render(handle, ctx, render_ctx, out)?;
      render_ctx.pop_block();
    }
  }
  Ok(())
}

Sample usage:

{{#populate str_key map=exampleMap}}
  {{exampleMapProperty}}
  {{@../parentVariable}}
{{/map}}

where:

exampleMap = HashMap<serde_json::Value::String, serde_json::Value>

@cryarchy
Copy link

@sunng87 I was investigating this earlier today and I realized that it now works. I think it is possible that the latest version fixed this. If that is not the case... dunno! Anyways, thank you. For this great project and for the quick and helpful responses.

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

Successfully merging a pull request may close this issue.

3 participants