Skip to content

Commit

Permalink
Fix inline partial parentNode problem
Browse files Browse the repository at this point in the history
Directives inside inline partials would get the fragment as the parentNode
if they are compiled before the partial is appended to the correct parentNode.
Therefore keep the reference of the fragment's childNodes, append it,
then compile afterwards fixes the problem.
  • Loading branch information
Evan You committed Jan 16, 2014
1 parent b63b551 commit 5f21eed
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 9 deletions.
27 changes: 22 additions & 5 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,20 +343,24 @@ CompilerProto.compileNode = function (node) {
* Compile a text node
*/
CompilerProto.compileTextNode = function (node) {

var tokens = TextParser.parse(node.nodeValue)
if (!tokens) return
var el, token, directive
var el, token, directive, partial, partialId, partialNodes

for (var i = 0, l = tokens.length; i < l; i++) {
token = tokens[i]
if (token.key) { // a binding
if (token.key.charAt(0) === '>') { // a partial
var partialId = token.key.slice(1).trim(),
partial = this.getOption('partials', partialId)
partialId = token.key.slice(1).trim()
partial = this.getOption('partials', partialId)
if (partial) {
el = partial.cloneNode(true)
this.compileNode(el)
// save an Array reference of the partial's nodes
// so we can compile them AFTER appending the fragment
partialNodes = slice.call(el.childNodes)
}
} else { // a binding
} else { // a real binding
el = document.createTextNode('')
directive = Directive.parse('text', token.key, this, el)
if (directive) {
Expand All @@ -366,7 +370,20 @@ CompilerProto.compileTextNode = function (node) {
} else { // a plain string
el = document.createTextNode(token)
}

// insert node
node.parentNode.insertBefore(el, node)

// compile partial after appending, because its children's parentNode
// will change from the fragment to the correct parentNode.
// This could affect directives that need access to its element's parentNode.
if (partialNodes) {
for (var j = 0, k = partialNodes.length; j < k; j++) {
this.compile(partialNodes[j])
}
partialNodes = null
}

}
node.parentNode.removeChild(node)
}
Expand Down
21 changes: 18 additions & 3 deletions test/functional/fixtures/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@
<body>

<div id="usa" v-partial="global"></div>
<div id="japan" v-partial="local"></div>
<div id="japan">{{> local}}</div>
<div id="repeat">{{> repeat}}</div>

<script type="text/v-template" id="test">
<p>{{hi}}!</p>
</script>

<script type="text/v-template" id="repeat-template">
<p v-repeat="items">{{title}}</p>
</script>

<script>

Vue.config({debug:true})
// Vue.config({debug:true})

// direct usage
var china = new Vue({
Expand Down Expand Up @@ -48,10 +53,20 @@
var japan = new Vue({
el: '#japan',
partials: {
local: document.querySelector('#test').innerHTML
local: '#test'
}
})
japan.hi = 'こんにちは'

var repeat = new Vue({
el: '#repeat',
partials: {
repeat: '#repeat-template'
},
data: {
items: [{ title: 'Repeat' }]
}
})
</script>
</body>
</html>
3 changes: 2 additions & 1 deletion test/functional/specs/template.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
casper.test.begin('Template', 4, function (test) {
casper.test.begin('Templates and Partials', 5, function (test) {

casper
.start('./fixtures/template.html')
Expand All @@ -7,6 +7,7 @@ casper.test.begin('Template', 4, function (test) {
test.assertSelectorHasText('#japan', 'こんにちは', 'local partial')
test.assertSelectorHasText('#china', '你好', 'direct option')
test.assertSelectorHasText('#hawaii', 'Aloha', 'extend option')
test.assertSelectorHasText('#repeat', 'Repeat', 'inline partial with repeat')
})
.run(function () {
test.done()
Expand Down

0 comments on commit 5f21eed

Please sign in to comment.