Регистрация  |  Вход

Рекурсивный вызов VF компонента

(получилось много текста - в 2-х словах в следующем сообщении)

Сколько лет не хотел использовать VF component ввиду их глючности и ограниченности, но сегодня пришлось. Хотел сделать красиво. В итоге как и ожидалось в самом финале уперся в проблему.

Задача: наверное банальнее некуда - построить дерево, например ролей.

Обычно такую задачу решаю рендерингом html прямо в контроллере в рекурсивной функции. Но сейчас стоит задача построить дерево с родными input для Salesforce. Чтобы можно было что-то отредактировать для каждой роли и отправить в контроллер на обработку обычным методом.

сделал RoleWrapper для Role__c, который будет содержать List подчиненных ролей (в виде RoleWrappers) для воссоздания иерархической структуры.



public with sharing class RoleWrapper {

public Role__c role { get; set; }

public List<RoleWrapper> childRoles { get; set; }

public RoleWrapper(Role__c role) {

this.role = role;

childRoles = new List<RoleWrapper>();

}

}



дерево в рекурсивной функции строится замечательно.

Теперь задача вывести это дерево на странице. Для этого сделал такой замечательный VF компонент, который вызывает самого себя для вывода всех подчиненных RoleWrappers

ShowRoleWrapper.component



<apex:component >

<apex:attribute name="rws" type="RoleWrapper[]" default="Default value for S attribute" description="test" />

<apex:repeat value="{!rws}" var="rw" >

<div class="level-{!rw.level}">

<div class="role-name">

{!rw.role.Name}

</div>

<c:ShowRoleWrapper rws="{!rw.childRoles}" />

</div>

</apex:repeat>

</apex:component>

на самой VF странице вызов всего одной строчкой

<c:ShowRoleWrapper rws="{!roleWrappers}" />

В итоге ошибка:

Cyclic page or component references '/apexcomponent/c__showrolewrapper' are not allowed

Как эту фигню можно победить? Чтобы не писать злые кастыли

[size=85]([i]получилось много текста - в 2-х словах в следующем сообщении[/i])[/size]


Сколько лет не хотел использовать VF component ввиду их глючности и ограниченности, но сегодня пришлось. Хотел сделать красиво. В итоге как и ожидалось в самом финале уперся в проблему.

Задача: наверное банальнее некуда - построить дерево, например ролей.

[i]Обычно такую задачу решаю рендерингом html прямо в контроллере в рекурсивной функции. Но сейчас стоит задача построить дерево с родными input для Salesforce. Чтобы можно было что-то отредактировать для каждой роли и отправить в контроллер на обработку обычным методом.[/i]

сделал RoleWrapper для Role__c, который будет содержать List подчиненных ролей (в виде RoleWrappers) для воссоздания иерархической структуры.
[code]
public with sharing class RoleWrapper {
	public Role__c role { get; set; }
	public List<RoleWrapper> childRoles { get; set; }

	public RoleWrapper(Role__c role) {
		this.role = role;
		childRoles = new List<RoleWrapper>();
	}
}
[/code]
дерево в рекурсивной функции строится замечательно.

Теперь задача вывести это дерево на странице. Для этого сделал такой замечательный VF компонент, который вызывает самого себя для вывода всех подчиненных RoleWrappers

ShowRoleWrapper.component
[code]
<apex:component >
	<apex:attribute name="rws" type="RoleWrapper[]" default="Default value for S attribute" description="test" />

	<apex:repeat value="{!rws}" var="rw" >
		<div class="level-{!rw.level}">
			<div class="role-name">
				{!rw.role.Name}
			</div>
			<c:ShowRoleWrapper rws="{!rw.childRoles}" />
		</div>
	</apex:repeat>

</apex:component>
[/code]

на самой VF странице вызов всего одной строчкой
[code]<c:ShowRoleWrapper rws="{!roleWrappers}" />[/code]

В итоге ошибка:
[b]Cyclic page or component references '/apexcomponent/c__showrolewrapper' are not allowed[/b]

Как эту фигню можно победить? Чтобы не писать злые кастыли

в 2-x словах - в Salesforce нельзя вызывать компонент рекурсивно?

в 2-x словах - в Salesforce нельзя вызывать компонент рекурсивно?

Не знаю, поможет ли это, но вот статья предложенная к изучению Артемом в соседней теме:

https://developer.salesforce.com/page/Dynamic_Visualforce_Components

"Обычно такую задачу решаю рендерингом html прямо в контроллере в рекурсивной функции"
но ведь можно в контроллере вместо HTML таким же образом создать оригинальные ВФ элементы? а это тебе вроде и нужно.

Не знаю, поможет ли это, но вот статья предложенная к изучению Артемом в соседней теме:

[url]https://developer.salesforce.com/page/Dynamic_Visualforce_Components[/url]

[i]"Обычно такую задачу решаю рендерингом html прямо в контроллере в рекурсивной функции"[/i]
но ведь можно в контроллере вместо HTML таким же образом создать оригинальные ВФ элементы? а это тебе вроде и нужно.

Может я не понимаю проблему но зачем было писать компонент,можно сделать два repeater вложенные друг в друга ?

Может я не понимаю проблему но зачем было писать компонент,можно сделать два repeater вложенные друг в друга ?

Я бы еще одну вещь проверил бы компоненты вроде как рендерятся во view state,Мне думается что не есть гуд с работать циклами для компонентов.

Я бы еще одну вещь проверил бы компоненты вроде как рендерятся во view state,Мне думается что не есть гуд с   работать циклами для компонентов.

Может я не понимаю проблему но зачем было писать компонент,можно сделать два repeater вложенные друг в друга ?

2 repeat вложенный друг в друга - это только 2 уровня. А если уровней N, то я устану эти repeat вкладывать друг в друга

Я бы еще одну вещь проверил бы компоненты вроде как рендерятся во view state,Мне думается что не есть гуд с работать циклами для компонентов.

Вот это пока не проверял. Но тут вся суть в том что компонент не имеет контроллера, и по логике он не должен поэтому жрать view state. Я только передаю ему через attribute объект, который мне нужно показать. Соотвественно в этом объекте есть еще лист таких же объектов которые точно также надо показать, а в этих объектах тоже есть список таких же объектов которые надо показать, а в этих ... короче так до бесконечности.

Млин обидно. Я то все время считал что компоненты именно для того и созданы чтобы показывать на странице повторяющиеся части.

[quote]Может я не понимаю проблему но зачем было писать компонент,можно сделать два repeater вложенные друг в друга ?[/quote]
2 repeat вложенный друг в друга - это только 2 уровня. А если уровней N, то я устану эти repeat вкладывать друг в друга

[quote]Я бы еще одну вещь проверил бы компоненты вроде как рендерятся во view state,Мне думается что не есть гуд с работать циклами для компонентов.[/quote]
Вот это пока не проверял. Но тут вся суть в том что компонент не имеет контроллера, и по логике он не должен поэтому жрать view state. Я только передаю ему через attribute объект, который мне нужно показать. Соотвественно в этом объекте есть еще лист таких же объектов которые точно также надо показать, а в этих объектах тоже есть список таких же объектов которые надо показать, а в этих ... короче так до бесконечности.

Млин обидно. Я то все время считал что компоненты именно для того и созданы чтобы показывать на странице повторяющиеся части.

Задачу конечно решил без компонентов, и получилось даже лучше чем я ожидал - лучше чем с компонентами если бы они заработали. Компонентам не зачет.

Задачу конечно решил без компонентов, и получилось даже лучше чем я ожидал - лучше чем с компонентами если бы они заработали. Компонентам не зачет.

Dmitry Shnyrev
Задачу конечно решил без компонентов, и получилось даже лучше чем я ожидал - лучше чем с компонентами если бы они заработали. Компонентам не зачет.

Хорошо что решил просто хотел услышать как ?

[quote="Dmitry Shnyrev"]Задачу конечно решил без компонентов, и получилось даже лучше чем я ожидал - лучше чем с компонентами если бы они заработали. Компонентам не зачет.[/quote]
Хорошо что решил просто хотел услышать как ?

Не стал заморачиваться с вложенными inner классами для описания древовидной структуры.
Сделал простой лист из inner классов, но добавил внутрь Integer level значение для задания отступа.

получилось из такого списка:
List<ClassWrapper>
- classWrapper 1 (level 0)
- classWrapper 2 (level 2)
- classWrapper 3 (level 3)
- classWrapper 4 (level 0)

вот такой вид на экране

- classWrapper 1
- classWrapper 2
- classWrapper 3
- classWrapper 4

такое псевдо дерево.

отступы формировались с помощью padding-left: {!20*level}px

вся хитрость как просчитать эти самые levels для classWrapper внутри контроллера. Хотя тут ничего особенного - та же самая рекурсия.

PS. сори если запутанно объяснил. Никогда не получалось объяснить алгоритм с рекурсией. Проще написать, чем объяснить :)

Не стал заморачиваться с вложенными inner классами для описания древовидной структуры.
Сделал простой лист из inner классов, но добавил внутрь Integer level значение для задания отступа.

получилось из такого списка:
List<ClassWrapper>
- classWrapper 1 (level 0)
- classWrapper 2 (level 2)
- classWrapper 3 (level 3)
- classWrapper 4 (level 0)

вот такой вид на экране 
[code]
- classWrapper 1
    - classWrapper 2
        - classWrapper 3
- classWrapper 4
[/code]

такое псевдо дерево.

отступы формировались с помощью padding-left: {!20*level}px

вся хитрость как просчитать эти самые levels для classWrapper внутри контроллера. Хотя тут ничего особенного - та же самая рекурсия.

PS. сори если запутанно объяснил. Никогда не получалось объяснить алгоритм с рекурсией. Проще написать, чем объяснить :)