sebastienros/fluid

[Custom Block] How to access the value between start and end of the block?

Closed this issue · 11 comments

For example:

{% foo %}
Hello
{% endfoo%}
parser.RegisterEmptyBlock("foo", (statements, writer, encoder, context) =>
{
    // how to access the value `Hello` here?
});

Try

return statements.RenderStatementsAsync(writer, encoder, context);

I want to access Hello inside RegisterEmptyBlock, I tried var result = statements.RenderStatementsAsync(writer, encoder, context); but that doesn't give me the Hello

Seems the above code will give you the result after rendering

Is the result equal to hello there?

It depends, if your block does nothing the code below should work

if not, you don't know what I am talking about, so please stop posting irrelevant comments

I know what I'm talking about, so be kind when you write your comments, what I mean in my comment is the code will return the result after rendering

parser.RegisterEmptyBlock("hello", static (writer, encoder, context) =>
{
    return s.RenderStatementsAsync(writer, encoder, context);
});

var template = parser.Parse("{% foo %} hello {%- endfoo %}");
var result = template.Render();

The result should be Hello

Please elaborate on what you are trying to do to avoid misunderstanding your question

Here is an example on how to use it. the block can contain "statements" that need to be processed. In your example it's a single Text Statement, but it could be another block, loops, ... You just need to process them all in order. Or evaluate them in a buffer and do something interesting with them.

[Fact]
public void ShouldRenderEmptyBlocks()
{
var parser = new CustomParser();
parser.RegisterEmptyBlock("hello", static (s, w, e, c) =>
{
w.Write("Hello World");
return s.RenderStatementsAsync(w, e, c);
});
var template = parser.Parse("{% hello %} hi {%- endhello %}");
var result = template.Render();
Assert.Equal("Hello World hi", result);
}

@sebastienros I saw that, actually I checked all test cases before posting the question here. that doesn't help me. you wrote a hard-coded value, Hello World to the output, but I need to access the hi part parser.RegisterEmptyBlock("hello", static (s, w, e, c) => { >>> HERE <<< });, do something with it, then write the result to output, how can I do that?

Assert.Equal("Hello World hi", result);

Can you see the "hi" here? Meaning it's written to the output, by this:

s.RenderStatementsAsync(w, e, c)

w is the "output text writer" so this code outputs anything from the withing the block ("hi") to the same source writer. If you want to intercept it, create a custom TextWriter, write it there, do something with the string then write the result to w.

I don't know why you didn't mention it, but the answer was writer.ToString();

parser.RegisterEmptyBlock("foo", (statements, writer, encoder, context) =>
{
    statements.RenderStatementsAsync(writer, encoder, context)
    var result = writer.ToString(); // result here is the value `Hello`
    // manipulate result
    writer.Write(result);
    return Statement.Normal();
});

Thank you for the help.

No, this won't work as-is. You need to create a new Text Writer or you will get the results from everything else that was written from previous tags too.

create a custom TextWriter

You are right, I used the following code:

_parser.RegisterEmptyBlock("foo", static (statements, writer, encoder, context) =>
{
	using (var sw = new StringWriter())
	{
		statements.RenderStatementsAsync(sw, encoder, context);
                var result = sw.ToString();
                // manipulate result
                writer.Write(result);
	}

	return Statement.Normal();
});