Я еще не разобрался с параметром проецируемых узлов в сочетании с ng-select
.
Но если вы посмотрите мой stackblitz вы можете видеть, как это работает .. вроде.
Что я узнал, что происходит:
ng-select
обрабатываются в перевернутом виде (я так думаю). Это означает, что он сначала обрабатывает последний выбор в шаблоне и проверяет последний массив в массиве 2-мерных проецируемых узлов
- Когда вы указываете запрос на выборку, и он не может найти его в соответствующем массиве, он просто показывает все элементы в массиве
- Первый
ng-select
соответствует первому массиву в массиве 2d.
- Если у вас есть узел, который находится в запросе выбора, а также добавить его в следующий массив, он не будет найден в первом выборе и по какой-то причине будет добавлен в следующий. Наоборот - не проблема.
Итак, если у вас есть это как динамический html:
<hello>
<span class="title">
Title
</span>
<span class="another-title">
Another title
</span>
The rest here of the content......
<div>Something else here</div>
</hello>
Вы должны сделать свои узлы следующими
const projectableNodes = [
[ nodes[1] ], // span class="title"
[ nodes[3] ], // span class="another-title"
[ nodes[0], nodes[2], nodes[4], nodes[5]]
];
Чтобы соответствовать такому шаблону:
<h1 class="hello-title">
<ng-content select=".title"></ng-content>
</h1>
<h2 class="hello-title">
<ng-content select=".another-title"></ng-content>
</h2>
<div class="hello-content">
<ng-content></ng-content>
</div>
Чтобы объяснить пункт 4 (и, возможно, пункт 1), если вы это сделаете:
const projectableNodes = [
[ nodes[1], nodes[3] ],
[ nodes[3] ],
[ nodes[0], nodes[2], nodes[4], nodes[5]]
];
Нет проблем. Если сделать наоборот:
const projectableNodes = [
[ nodes[1] ],
[ nodes[3], nodes[1] ],
[ nodes[0], nodes[2], nodes[4], nodes[5]]
];
Он никогда не будет проецировать узлы [1] в правильном положении, но каким-то образом будет добавлен ко второму <ng-content>
с «другим заголовком». Я нашел этот ответ, который имеет несколько голосов, но мне не очень понятно, как работает механизм , или каким образом вы сможете сделать это динамичным.
Я надеюсь, что это даст вам некоторое представление, и, возможно, вы сможете придумать динамическое решение и опубликовать свой собственный ответ. Или, возможно, это была вся информация, которая вам нужна, и я действительно помог вам :D кто знает
Заглянув немного в исходный код, вы можете узнать количество ng-content
, которое у вас есть в вашем элементе. Это определяется factory.ngContentSelectors
. В моем stackblitz это:
0: ".title"
1: ".another-title"
2: "*"
Затем вы можете использовать метод Element.matches()
, чтобы выбрать этот содержимое, а остальное передать подстановочному знаку. Затем вы можете сделать его динамическим, используя следующую логику:
const nodes = Array.from(element.childNodes);
const selectors = this.factory.ngContentSelectors;
const projectableNodes = selectors.map(() => []);
const wildcardIdx = selectors.findIndex((selector) => selector === '*');
nodes.forEach((node) => {
if (node instanceof Element) {
// get element node that matches a select which is not the wildcard
const projectedToIdx = selectors.findIndex(
(selector, i) => i !== wildcardIdx && node.matches(selector)
);
if (projectedToIdx !== -1) {
// add it to the corresponding projectableNodes and return
projectableNodes[projectedToIdx].push(node);
return;
}
}
if (wildcardIdx > -1) {
// when there is a wildcard and it's not an Element or it cannot be,
// matched to the selection up, add it to the global ng-content
projectableNodes[wildcardIdx].push(node);
}
});
console.log('projectableNodes', projectableNodes);
const embeddedComponent = this.factory.create(
this.injector,
projectableNodes,
element
);
Я предполагаю, что это можно оптимизировать, или, возможно, здесь есть какие-то ошибки, но я надеюсь, что вы поняли идею. С такой логикой или чем-то подобным вы можете иметь относительно динамические компоненты с динамическими ng-content
person
Poul Kruijt
schedule
19.05.2020