Skip to content

Commit

Permalink
Merge pull request alpinejs#748 from ryangjchandler/feature/x-for-ove…
Browse files Browse the repository at this point in the history
…r-range

feature(x for over range)
  • Loading branch information
calebporzio authored Sep 5, 2020
2 parents 999356a + db28749 commit 302b251
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 8 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,16 @@ You can nest `x-for` loops, but you MUST wrap each loop in an element. For examp
</template>
```

#### Iterating over a range

Alpine supports the `i in n` syntax, where `n` is an integer, allowing you to iterate over a fixed range of elements.

```html
<template x-for="i in 10">
<span x-text="i"></span>
</template>
```

---

### `x-transition`
Expand Down
24 changes: 17 additions & 7 deletions dist/alpine-ie11.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
return module = { exports: {} }, fn(module, module.exports), module.exports;
}

(function(){function n(){function v(){return null}function l(a){return a?"object"===typeof a||"function"===typeof a:!1}function p(a){if(null!==a&&!l(a))throw new TypeError("Object prototype may only be an Object or null: "+a);}var q=null,e=Object,w=!!e.create||!({__proto__:null}instanceof e),A=e.create||(w?function(a){p(a);return {__proto__:a}}:function(a){function c(){}p(a);if(null===a)throw new SyntaxError("Native Object.create is required to create objects with null prototype");c.prototype=a;return new c}),
B=e.getPrototypeOf||([].__proto__===Array.prototype?function(a){a=a.__proto__;return l(a)?a:null}:v);var m=function(a,c){function k(){}if(void 0===(this&&this instanceof m?this.constructor:void 0))throw new TypeError("Constructor Proxy requires 'new'");if(!l(a)||!l(c))throw new TypeError("Cannot create proxy with a non-object as target or handler");q=function(){a=null;k=function(b){throw new TypeError("Cannot perform '"+b+"' on a proxy that has been revoked");};};setTimeout(function(){q=null;},0);var g=
c;c={get:null,set:null,apply:null,construct:null};for(var h in g){if(!(h in c))throw new TypeError("Proxy polyfill does not support trap '"+h+"'");c[h]=g[h];}"function"===typeof g&&(c.apply=g.apply.bind(g));g=B(a);var r=!1,t=!1;if("function"===typeof a){var f=function(){var b=this&&this.constructor===f,d=Array.prototype.slice.call(arguments);k(b?"construct":"apply");return b&&c.construct?c.construct.call(this,a,d):!b&&c.apply?c.apply(a,this,d):b?(d.unshift(a),new (a.bind.apply(a,d))):a.apply(this,
d)};r=!0;}else a instanceof Array?(f=[],t=!0):f=w||null!==g?A(g):{};var x=c.get?function(b){k("get");return c.get(this,b,f)}:function(b){k("get");return this[b]},C=c.set?function(b,d){k("set");c.set(this,b,d,f);}:function(b,d){k("set");this[b]=d;},y={};e.getOwnPropertyNames(a).forEach(function(b){if(!((r||t)&&b in f)){var d=e.getOwnPropertyDescriptor(a,b);e.defineProperty(f,b,{enumerable:!!d.enumerable,get:x.bind(a,b),set:C.bind(a,b)});y[b]=!0;}});h=!0;if(r||t){var D=e.setPrototypeOf||([].__proto__===
Array.prototype?function(b,d){p(d);b.__proto__=d;return b}:v);g&&D(f,g)||(h=!1);}if(c.get||!h)for(var u in a)y[u]||e.defineProperty(f,u,{get:x.bind(a,u)});e.seal(a);e.seal(f);return f};m.revocable=function(a,c){return {proxy:new m(a,c),revoke:q}};return m}var z="undefined"!==typeof process&&"[object process]"==={}.toString.call(process)||"undefined"!==typeof navigator&&"ReactNative"===navigator.product?commonjsGlobal:self;z.Proxy||(z.Proxy=n(),z.Proxy.revocable=z.Proxy.revocable);})();
(function(){function k(){function p(a){return a?"object"===typeof a||"function"===typeof a:!1}var l=null;var n=function(a,c){function g(){}if(!p(a)||!p(c))throw new TypeError("Cannot create proxy with a non-object as target or handler");l=function(){a=null;g=function(b){throw new TypeError("Cannot perform '"+b+"' on a proxy that has been revoked");};};setTimeout(function(){l=null;},0);var f=c;c={get:null,set:null,apply:null,construct:null};for(var h in f){if(!(h in c))throw new TypeError("Proxy polyfill does not support trap '"+
h+"'");c[h]=f[h];}"function"===typeof f&&(c.apply=f.apply.bind(f));var d=this,q=!1,r=!1;"function"===typeof a?(d=function(){var b=this&&this.constructor===d,e=Array.prototype.slice.call(arguments);g(b?"construct":"apply");return b&&c.construct?c.construct.call(this,a,e):!b&&c.apply?c.apply(a,this,e):b?(e.unshift(a),new (a.bind.apply(a,e))):a.apply(this,e)},q=!0):a instanceof Array&&(d=[],r=!0);var t=c.get?function(b){g("get");return c.get(this,b,d)}:function(b){g("get");return this[b]},w=c.set?function(b,
e){g("set");c.set(this,b,e,d);}:function(b,e){g("set");this[b]=e;},u={};Object.getOwnPropertyNames(a).forEach(function(b){if(!((q||r)&&b in d)){var e={enumerable:!!Object.getOwnPropertyDescriptor(a,b).enumerable,get:t.bind(a,b),set:w.bind(a,b)};Object.defineProperty(d,b,e);u[b]=!0;}});f=!0;Object.setPrototypeOf?Object.setPrototypeOf(d,Object.getPrototypeOf(a)):d.__proto__?d.__proto__=a.__proto__:f=!1;if(c.get||!f)for(var m in a)u[m]||Object.defineProperty(d,m,{get:t.bind(a,m)});Object.seal(a);Object.seal(d);
return d};n.revocable=function(a,c){return {proxy:new n(a,c),revoke:l}};return n}var v="undefined"!==typeof process&&"[object process]"==={}.toString.call(process)||"undefined"!==typeof navigator&&"ReactNative"===navigator.product?commonjsGlobal:self;v.Proxy||(v.Proxy=k(),v.Proxy.revocable=v.Proxy.revocable);})();

!function(e){var t=e.Element.prototype;"function"!=typeof t.matches&&(t.matches=t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||function(e){for(var t=(this.document||this.ownerDocument).querySelectorAll(e),o=0;t[o]&&t[o]!==this;)++o;return Boolean(t[o])}),"function"!=typeof t.closest&&(t.closest=function(e){for(var t=this;t&&1===t.nodeType;){if(t.matches(e))return t;t=t.parentNode;}return null});}(window);

Expand Down Expand Up @@ -6361,10 +6360,21 @@
}

function evaluateItemsAndReturnEmptyIfXIfIsPresentAndFalseOnElement(component, el, iteratorNames, extraVars) {
var _this4 = this;

var ifAttribute = getXAttrs(el, component, 'if')[0];

if (ifAttribute && !component.evaluateReturnExpression(el, ifAttribute.expression)) {
return [];
} // This adds support for the `i in n` syntax.


if (isNumeric(iteratorNames.items)) {
return Array.from(Array(parseInt(iteratorNames.items, 10)).keys(), function (i) {
_newArrowCheck(this, _this4);

return i + 1;
}.bind(this));
}

return component.evaluateReturnExpression(el, iteratorNames.items, extraVars);
Expand Down Expand Up @@ -6397,12 +6407,12 @@
var nextElementFromOldLoop = currentEl.nextElementSibling && currentEl.nextElementSibling.__x_for_key !== undefined ? currentEl.nextElementSibling : false;

var _loop = function _loop() {
var _this4 = this;
var _this5 = this;

var nextElementFromOldLoopImmutable = nextElementFromOldLoop;
var nextSibling = nextElementFromOldLoop.nextElementSibling;
transitionOut(nextElementFromOldLoop, function () {
_newArrowCheck(this, _this4);
_newArrowCheck(this, _this5);

nextElementFromOldLoopImmutable.remove();
}.bind(this), component);
Expand Down
5 changes: 5 additions & 0 deletions dist/alpine.js
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,11 @@

if (ifAttribute && !component.evaluateReturnExpression(el, ifAttribute.expression)) {
return [];
} // This adds support for the `i in n` syntax.


if (isNumeric(iteratorNames.items)) {
return Array.from(Array(parseInt(iteratorNames.items, 10)).keys(), i => i + 1);
}

return component.evaluateReturnExpression(el, iteratorNames.items, extraVars);
Expand Down
11 changes: 11 additions & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,17 @@
</td>
</tr>

<tr>
<td>x-for over a range using <code>i in 10</code> syntax</td>
<td>
<div x-data>
<template x-for="i in 10" :key="i">
<span x-text="i"></span>
</template>
</div>
</td>
</tr>

<tr>
<td>Transitions</td>
<td>
Expand Down
7 changes: 6 additions & 1 deletion src/directives/for.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { transitionIn, transitionOut, getXAttrs, warnIfMalformedTemplate } from '../utils'
import { transitionIn, transitionOut, getXAttrs, warnIfMalformedTemplate, isNumeric } from '../utils'

export function handleForDirective(component, templateEl, expression, initialUpdate, extraVars) {
warnIfMalformedTemplate(templateEl, 'x-for')
Expand Down Expand Up @@ -92,6 +92,11 @@ function evaluateItemsAndReturnEmptyIfXIfIsPresentAndFalseOnElement(component, e
return []
}

// This adds support for the `i in n` syntax.
if (isNumeric(iteratorNames.items)) {
return Array.from(Array(parseInt(iteratorNames.items, 10)).keys(), i => i + 1)
}

return component.evaluateReturnExpression(el, iteratorNames.items, extraVars)
}

Expand Down
14 changes: 14 additions & 0 deletions test/for.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -477,3 +477,17 @@ test('make sure new elements with different keys added to the beginning of a loo

expect(clickCount).toEqual(2)
})

test('x-for over range using i in x syntax', async () => {
document.body.innerHTML = `
<div x-data>
<template x-for="i in 10">
<span x-text="i"></span>
</template>
</div>
`

Alpine.start()

expect(document.querySelectorAll('span').length).toEqual(10)
})

0 comments on commit 302b251

Please sign in to comment.