Permalink
Browse files

fixes inline recursive partials

  • Loading branch information...
justinbmeyer committed Nov 8, 2018
1 parent e96e964 commit 58d1ee9cc143eb23981aaa3c3fc6831eff1bc005
Showing with 138 additions and 43 deletions.
  1. +23 −0 docs/tags/else.md
  2. +75 −41 docs/tags/named-partial.md
  3. +2 −0 docs/tags/section.md
  4. +8 −0 expressions/call.js
  5. +1 −1 helpers/-converter-test.js
  6. +28 −0 test/partials-test.js
  7. +1 −1 test/test.html
@@ -6,6 +6,29 @@
Creates an `FALSY` block for a [can-stache.helper helper function]’s
[can-stache.helperOptions options argument]’s `inverse` property.

The following creates a `isSquare` helper that renders the `FALSY` section
if the number is not a perfect square:

```js
import {stache} from "can";
const view = stache(`<div>{{# isSquare(3) }}YES{{else}}NO{{/ isSquare}}</div>`);
stache.addHelper("isSquare", function(num, options){
if( Number.isInteger( Math.sqrt(num) ) ) {
return options.fn();
} else {
return options.inverse();
}
});
var fragment = view();
console.log(fragment.firstChild.innerHTML) //-> NO
document.body.appendChild(fragment);
```
@codepen

@param {can-stache.sectionRenderer} FALSY A partial stache template
converted into a function and set as the [can-stache.helper helper function]’s
[can-stache.helperOptions options argument]’s `inverse` property.
@@ -5,15 +5,38 @@ Create an inline named partial within the current template.

@signature `{{<partialName}}BLOCK{{/partialName}}`

Creates a reusable sub-template from `BLOCK` named `partialName` that can be rendered with `{{ partialName() }}`.
Creates a reusable sub-template from `BLOCK` named `partialName` that can be rendered
with `{{ partialName() }}`. The following creates an `addressView` partial and
renders it with two addresses:

For example, the following defines an `addressView` and uses it to render several addresses:
```js
import {stache} from "can";
- called with an object, set
const view = stache(`
{{<addressView}}
<address>{{this.street}}, {{this.city}}</address>
{{/addressView}}
@param {String} partialName The name of the partial.
<article>
{{addressView(this.address1)}}
{{addressView(this.address2)}}
</article>
`)
@param {can-stache.sectionRenderer} BLOCK a template to be captured and rendered later.
const fragment = view({
address1: {street: "Bitovi Way", city: "World" },
address2: {street: "Stave", city: "Chicago" }
});
console.log(fragment.firstChild.innerHTML)
//-> <address>...</address><address>...</address>
document.body.appendChild(fragment);
```
@codepen

@param {String} partialName The name of the partial.

@param {can-stache.sectionRenderer} BLOCK a template to be captured and rendered later.



@@ -83,49 +106,60 @@ Component.extend({
```
@codepen

Named partials can also have a template block that references its own name in a [can-stache.tags.partial partial tag], which creates recursion. (So make sure you avoid infinite loops!)
Named partials can also references their own name in a [can-stache.tags.partial partial tag], which creates recursion.

Given this data:
```html
<partial-demo></partial-demo>

```js
{
yayRecursion: {
name: "Root",
nodes: [
{
name: "Leaf #1 in Root",
nodes: []
},
{
name: "Branch under Root",
nodes: [
{
name: "Leaf in Branch",
nodes: []
}
]
},
{
name: "Leaf #2 in Root",
nodes: []
<script type="module">
import {Component} from "can";
Component.extend({
tag: "partial-demo",
view: `
{{< recursiveView }}
<div>{{this.name}} <b>Type:</b> {{#if(this.nodes.length)}}Branch{{else}}Leaf{{/if}}</div>
{{# for(node of this.nodes) }}
{{ recursiveView(node) }}
{{/ for }}
{{/ recursiveView }}
{{ recursiveView(this.yayRecursion) }}
`,
ViewModel: {
yayRecursion: {
default(){
return {
name: "Root",
nodes: [
{
name: "Leaf #1 in Root",
nodes: []
},
{
name: "Branch under Root",
nodes: [
{
name: "Leaf in Branch",
nodes: []
}
]
},
{
name: "Leaf #2 in Root",
nodes: []
}
]
}
}
]
}
}
}
});
</script>
```
@codepen

This template:

```handlebars
{{<recursive}}
<div>{{./name}} <b>Type:</b> {{#if(./nodes.length)}}Branch{{else}}Leaf{{/if}}</div>
{{#each(./nodes)}}
{{>recursive .}}
{{/each}}
{{/recursive}}

{{>recursive yayRecursion}}
```

Would result in:

@@ -27,6 +27,7 @@ or the expression’s return value.
document.body.appendChild(fragment);
```
@codepen

Different helpers can render these sections multiple times. [can-stache.helpers.else]
also defines a `FALSY` section that helpers can call. In the following, [can-stache.helpers.for-of]
@@ -48,6 +49,7 @@ or the expression’s return value.
document.body.appendChild(fragment);
```
@codepen

Helpers can control the variables and context accessible in the `TRUTHY`
and `FALSY` section. Read [can-stache.addHelper] and
@@ -10,6 +10,7 @@ var assign = require('can-assign');

var sourceTextSymbol = canSymbol.for("can-stache.sourceText");
var isViewSymbol = canSymbol.for("can.isView");
var Scope = require("can-view-scope");

// ### Call
// `new Call( new Lookup("method"), [new ScopeExpr("name")], {})`
@@ -83,7 +84,14 @@ Call.prototype.value = function(scope, helperOptions){
args.push(helperOptions);
}
}
// we are calling a view!
if(func[isViewSymbol] === true) {
// if not a scope, we should create a scope that
// includes the template scope
if(!(args[0] instanceof Scope)){
args[0] = scope.getTemplateContext().add(args[0]);
}
// and include nodeLists
args.push(helperOptions.nodeList);
}
if(arguments.length) {
@@ -137,7 +137,7 @@ QUnit.test("not works also like if", function(){
});

QUnit.test("not works inside if", function(){
var view = stache("<div>{{#if( not(this.value) ) }}{{truthy(this)}}{{else}}FALSY{{/not}}</div>");
var view = stache("<div>{{#if( not(this.value) ) }}{{truthy(this)}}{{else}}FALSY{{/if}}</div>");

var data = new SimpleMap({
value: false
@@ -526,3 +526,31 @@ QUnit.test("inline partials are accessible from call expressions", 1, function()

QUnit.equal(frag.firstChild.firstChild.innerHTML, "Stave");
});

QUnit.test("recursive inline partials are accessible from call expressions", 1, function(){

var view = stache(
"{{<folderPartial}}"+
"<span>{{this.name}}</span>"+
"{{#if(this.folder)}}<div>{{ folderPartial(this.folder) }}</div>{{/if}}"+
"{{/folderPartial}}"+
"<div>{{ folderPartial(this.folder) }}</div>"
);

var frag = view({
folder: {
name: "Parent",
folder: {
name: "Child",
folder: null
}
}
});

var spans = frag.firstElementChild.getElementsByTagName("span");
var spanText = [].slice.call(spans,0).map(function(span){
return span.innerHTML;
});

QUnit.deepEqual(spanText, ["Parent", "Child"]);
});
@@ -1,4 +1,4 @@
<!doctype html>
<title>can-stache</title>
<script src="../node_modules/steal/steal.js" main="can-stache/test/stache-test"></script>
<script src="../node_modules/steal/steal-sans-promises.js" main="can-stache/test/stache-test"></script>
<div id="qunit-fixture"></div>

0 comments on commit 58d1ee9

Please sign in to comment.