XaminProject / handlebars.php

Handlebars processor for php
331 stars 134 forks source link

Render with partials #93

Closed g84 closed 9 years ago

g84 commented 9 years ago
$engine = new Handlebars();
$data = [];

// I don't need global partials
//$engine->registerPartial('partial_1', '<span />');
//$engine->registerPartial('partial_2', '<span />');
//$engine->render('<div />', $data)

// more dynamically
$engine->render('<div />', $data, [
  'partial_1' => '<span />',
  'partial_2' => '<span />',
]);

$engine->render('<div />', $data, [
  'partial_1' => '<span />',
  'partial_3' => '<span />',
]);
everplays commented 9 years ago

Hmm. You could easily do it by extending Handlerbars\Handlebars class and overriding loadPartial and render methods in your program.

Also patches are welcome. However, I think for the patch, it would make more sense to have it as a Loader instance instead of array. So it would be more like:

$engine->render('<div />', $data, [
  "partials_loader" => new ArrayLoader([
    'partial_1' => '<span />',
    'partial_3' => '<span />',
  ])
  // or other options
]);

@fzerorubigd thoughts?

JustBlackBird commented 9 years ago

As I see, the proposed behavior is not compatible with handlebars.js.

everplays commented 9 years ago

@JustBlackBird but from my understanding it's about API and not about the syntax of templates, helpers, etc. Our API is already different from js implementation, right? Please, let us know if you still think it shouldn't be added.

JustBlackBird commented 9 years ago

@everplays you are right, the APIs are different, but both PHP and JS versions are using global partials now.

@g84, could you describe your use case that makes global partials useless?

fzerorubigd commented 9 years ago

The api is different already, but I can not see any use for this. In any case, one can use unregisterPartial right after render :

$engine->registerPartial('partial_1', '<span />');
$engine->registerPartial('partial_2', '<span />');
$engine->render('<div />', $data)
$engine->unRegisterPartial('partial_1');
$engine->unRegisterPartial('partial_2');
g84 commented 9 years ago

I make experimental site, which consists of independent components. Each component contains some logic in php and has a template. Each component may include other components. For example, as here https://drive.google.com/file/d/0B8K6ZzqIXOr2dmlXV1V2Z2l2Wjg/view. In this case, to render product_card I need to LOCALLY set partials: cart_button and product_rating and render product_card template. Then I need to render more of the other components with the same instance:

$engine = new Handlebars();
JustBlackBird commented 9 years ago

@g84, so why don't you use global partials? product_rating and cart_button templates are the same for all product cards. Or may be I've missed something?

g84 commented 9 years ago

Each component renders itself and its children in it LOCAL scope. This component need only partials that relate to it (product_rating and cart_button) - it does not need global garbage. Names of parts are NOT global.

It seems quite natural rendering with global or local partialls.

g84 commented 9 years ago

As far as I know a mustache.js knows how to do it:

Writer.prototype.render = function (template, view, partials) {
    var tokens = this.parse(template);
    var context = (view instanceof Context) ? view : new Context(view);
    return this.renderTokens(tokens, context, partials, template);
  };
JustBlackBird commented 9 years ago

I think you can use namespaces for partials:

$engine->registerPartial('components/product_card/partial_1', '<span />');
$engine->registerPartial('components/product_card/partial_2', '<span />');
$engine->render('<div />', $data);
g84 commented 9 years ago

This is not bad solution, @JustBlackBird, thank you.

JustBlackBird commented 9 years ago

You are welcome, @g84.

everplays commented 9 years ago

thanks @JustBlackBird. I am closing it.