• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Получить компонент в N-ой строке Xp:repeat'а (xpages)

  • Автор темы Zeka
  • Дата начала
Z

Zeka

Есть xp:repeat который отображает несколько строк с документами. Каждая строка содержит некий компонент (например xe:dialog).
Вопрос - как в SSJS развернуть диалог находящемуся на N-ой строчке репита?

Как вообще можно получить доступ к компоненту на определённой строке?
 
H

hosm

Соррь, я не в теме по вопросу, но форум link removed не для этого???

Добавлено: в общем, я перенесу с оставленной ссылкой тут. Если что, вернут)
 
Z

Zeka

Соррь, я не в теме по вопросу, но форум link removed не для этого???

Добавлено: в общем, я перенесу с оставленной ссылкой тут. Если что, вернут)

Упс... Я и не знал, что по xPages есть отдельная ветка....
Да, это вопрос чисто по xPages...
 
D

Dragon108

Есть примерно такой же вопрос:

Есть рипит контрол - отображает данные из представления. В каждой строчке рипита так же есть: поле (Input Box) и Кнопка. По клику на Кнопку надо брать данные из инпут бокса (соответствующего данной строчке рипита) - туда данные вводят вручную, и обрабатывать их на сервере. Так вот как это можно сделать?

Пробовал по такому сценарию: . Не подходит - инпут поля в рипите множатся, но алиас у них один :( Введенные данные на сервере берутся некорректно.

Пробовал так же в Data Source Инпут поля прописывать ['Alias' + rowIndex] через Scope переменную, где rowIndex - Index name в Рипит контроле. Выдается ошибка
com.sun.faces.el.impl.ElException: An exception occured trying to convert String "Alias" to type "java.lang.Long"
An exception occured trying to convert String "Alias" to type "java.lang.Long"



P.S. Есть ли вообще такая техническая возможность при помощи обычного рипит контрола? Или стоит копать в пользу готовых контролов - например Dojo Data Grid?
 

NickProstoNick

Статус как статус :)
Lotus Team
22.08.2008
1 851
27
BIT
0
можно сделать немного по другому.
Можно использовать один диалог для всех документов. Причем диалог грузить динамически и передавать в него документ.
Вызывать диалог, например, по клику на строку документа или по кнопке в репитконтроле
 
D

Dragon108

можно сделать немного по другому.
Можно использовать один диалог для всех документов. Причем диалог грузить динамически и передавать в него документ.
Вызывать диалог, например, по клику на строку документа или по кнопке в репитконтроле

А можно чуть поподробнее?
Т.е. при клике на док в рипит контроле открывается всплывающее окно (диалог бокс) с Интпут боксом куда вводятся необходимые данные? и дальше, после закрытия всплывающего окна, данные обрабатываются на сервере?
 

NickProstoNick

Статус как статус :)
Lotus Team
22.08.2008
1 851
27
BIT
0
А можно чуть поподробнее?
Т.е. при клике на док в рипит контроле открывается всплывающее окно (диалог бокс) с Интпут боксом куда вводятся необходимые данные? и дальше, после закрытия всплывающего окна, данные обрабатываются на сервере?
Именно.

документ из репитера
JavaScript:
<Collection name>.getDocument()
Идентификатор из репитера
JavaScript:
<Collection name>.getNoteID()
<Collection name>.getUniversalID()
Есть функция динамической загрузки кастом-контролов
JavaScript:
function loadCC( Name: String, parent: String, index, delChildren: boolean ){

//get panel control as parent of the custom control to include
//var objParent = getComponent( "panel_0" );

var objParent = getComponent( parent );

if( delChildren == true ){

if (objParent.getChildren().size() > 0) {
objParent.getChildren().clear();
}
}

//page name of the custom control to include
var strPageName = "/" + Name;

//create new UIIncludeComposite
var objControl = new com.ibm.xsp.component.UIIncludeComposite();

//set the page name to the UIIncludeComposite object
objControl.setPageName(strPageName);

//Ensure a unique id for this control
objControl.setId( "i_"+ index );       

//objControl.setId( index );

//Create a builder object from XPages Extension Library
var objBuilder = new com.ibm.xsp.extlib.builder.ControlBuilder();

//to use the builder you need ControlImpl objects.
//Because this builder only can work with those objects
//get the class of ControlImpl
var classControlImpl = objBuilder.getClass().getDeclaredClasses()[1];

//create an ControlImpl object of the parent panel
var objImplParent = new classControlImpl(objParent);

//create an ControlImpl object of the custom control
var objImplControl = new classControlImpl(objControl);

//add the new custom control to the parent
objImplParent.addChild(objImplControl);

//build the updated parent control
objBuilder.buildControl(facesContext,objImplParent,false);   

}
На входе имя кастом-котрола. Например Name = "cc_test.xsp". Расширение в коде обязательно! Хотя в списке дизайнера указывается только имя!
index - имя, которое присвоится кастом-контролу . После загрузки к этому имени допишется префикс "i_"
parent - имя контрола, в который будем добавлять свой кастом-контрол.
Я для этого добавляю в конец страницы пустую панель. В ней не жалко удалять не нужные объекты по delChildren.

Если у кастом-контрола есть Property Definition - берем свойства и присваиваем то что надо. Типы данных обязательно соблюдаем.
Передать можно строки, числа, объекты. Подробнее или
Вот пример как передать юнид документа в кастом-контрол. При условии что в кастом-контроле есть уже объект документа. В самом же кастом-контроле параметр берется через compositeData
JavaScript:
var cmp:com.ibm.xsp.component.UIIncludeComposite = getComponent( "i_" + ndex );
cmp.getPropertyMap().setString("docUnid", document1.getUniversalID() );
Если надо передать именно объект документа в кастом-контрол:
JavaScript:
var cmp:com.ibm.xsp.component.UIIncludeComposite = getComponent( "i_" + ndex );
cmp.getPropertyMap().setProperty("document", document1);
Соответственно все работы в кастом-контроле ведутся через compositeData.
Если же кастом-контрол является частью одного документа - в кастом-контроле не нужны никакие объекты документа.
В свойствах Data Binding контрола в кастом-контроле можно просто написать Data source и Bind to объект основной страницы

Чтоб открыть диалог - все как всегда при помощи SSJS или CSJS
JavaScript:
var d = getComponent( "dialog1" );
d.show()
Для пущего феншуя в кастом-контрол с диалогом добавляю параметры для рефреша компонентов после закрытия диалога и так же передаю код, который может выполняться по кнопке Ok в диалоге

Таким методом можно создавать динамические страницы. Определять кастом-контролы до загрузки страницы.
Этим методом разношу логику. В дизайнере работать удобно. Страницы получаются практически пустые.
 
Последнее редактирование модератором:
A

alexas

Поддерживаю технологию, которую описал NickProstoNick. Сам дизайню так-же.
Работать очень удобно и вся логика абсолютно прозрачна. Особенно для тех, кто только пришёл в xpages из классического клиента.
У новичков всегда возникает вопрос: как в хепагах дизайнить фреймы?
Вот так - с помощью loadCC (у меня ещё replaceCC) грузить кастом-контролы или задизайненные страницы(!) (тут надо быть внимательным - не каждая хепага загрузится без ошибок!) в нужные места предварительно размеченной главной страницы (дивами, панелями, таблицей... кому что нравится).
Т.е. это эквивалент связки SetTargetFrame & OpenPage(Form...) в классике.
Результат - полностью динамичная страница.
Часто всё WEB приложение обходится ей одной (если не нужен функционал с параллельной логикой в двух и более вкладках браузера).
Как вообще можно получить доступ к компоненту на определённой строке?
Делаете имя Вашего контрола, который размножаете в репитере, вычисляемым - например Name: MyControl_${rptIndex}, где rptIndex - это Index Name репитера (Options).
Name (id) контрола в Properties дизайнер поправить не даст - надо править в коде (Sourse).
Далее, как обычно, получаете компонент по id: getComponent('MyControl_' + i), где i - индекс компонента в строке (или колонке) репитера.
 
D

Dragon108

Делаете имя Вашего контрола, который размножаете в репитере, вычисляемым - например Name: MyControl_${rptIndex}, где rptIndex - это Index Name репитера (Options).
Name (id) контрола в Properties дизайнер поправить не даст - надо править в коде (Sourse).
Далее, как обычно, получаете компонент по id: getComponent('MyControl_' + i), где i - индекс компонента в строке (или колонке) репитера.

Можно, если не сложно, пример.
При прописывании в атрибуте id - MyControl_${rptIndex} в теге xp:inputText - в итоговой html странице элементы inputText имеют id-шники MyControl_. :(


P.S. Да и вообще нашел вот такую вещь -

The identifier must be a static value.
 

NickProstoNick

Статус как статус :)
Lotus Team
22.08.2008
1 851
27
BIT
0
rptIndex - это значение свойства Index control репитера
И что должны были вынести из твоей ссылки?

Вообще - надо понимать что вообще надо делать!
А то каким местом связаны диалоговые окна с доступом к какому-то определенному контролу в репитере?

Как будет определяться в какой строке репитера надо обратиться?
 
D

Dragon108

rptIndex - это значение свойства Index control репитера
И что должны были вынести из твоей ссылки?

То, что значение id у элемента (в данном случае это InputBox) - всегда статично, т.е. насколько я понял (ссудя из ссылки хелпа выше) вычислять его нельзя - можно только "намертво вбить". Или я чего то не понял/не знаю и прошу рассказать как можно это id - вычислять.
 

NickProstoNick

Статус как статус :)
Lotus Team
22.08.2008
1 851
27
BIT
0
блин.. руками вбить!
Тебе же написали
Делаете имя Вашего контрола, который размножаете в репитере, вычисляемым - например Name: MyControl_${rptIndex}, где rptIndex - это Index Name репитера (Options).
Name (id) контрола в Properties дизайнер поправить не даст - надо править в коде (Sourse).
Далее, как обычно, получаете компонент по id: getComponent('MyControl_' + i), где i - индекс компонента в строке (или колонке) репитера.
У репитера надо указать 3 свойства:
  1. Data Source
  2. var (оно же Collection name)
  3. indexVar (оно же Index name) надо в нем написать rptIndex

В свойстве Name поля написать код
Код:
"MyControl_" + rptIndex
 
D

Dragon108

Видимо вы меня неправильно поняли ... бывает :(

Был бы рад простому примеру как у вас получилось вот это:

В свойстве Name поля написать код
Код:
"MyControl_" + rptIndex


P.S. Если в поле прописать id="MyControl_${rptIndex}", где rptIndex - indexVar (оно же Index name). то в итоговой html-странице все поля в репит контроле получаются с id: MyControl_.
Все остальное (из вашей инструкции - уже сделано)
 

NickProstoNick

Статус как статус :)
Lotus Team
22.08.2008
1 851
27
BIT
0
Код:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex">

<xp:repeat id="repeat1" rows="30" var="colName" indexVar="rptIndex"
repeatControls="true">
<xp:this.value><![CDATA[#{java script:var tmp = []
tmp.push("1111111111") 
tmp.push("2222222222")
tmp.push("3333333333")
tmp.push("4444444444")
tmp.push("5555555555")
return tmp}]]></xp:this.value>
<xp:inputText value="#{java script:colName}">

<xp:this.id><![CDATA[${java script:"MyControl_" + rptIndex}]]></xp:this.id>
</xp:inputText>

<xp:br></xp:br>
</xp:repeat>
</xp:view>
 
A

alexas

Dragon108
Может так будет понятней
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

<xp:text escape="true" id="sourceRepeat"><xp:this.value><![CDATA[#{java script:['111','222','333','444','555']}]]></xp:this.value></xp:text>
<xp:br></xp:br>
<xp:repeat id="repeat2" rows="30" indexVar="rptIndex"
repeatControls="true">
<xp:this.value>
<![CDATA[#{java script:getComponent("sourceRepeat").getValue()}]]>
</xp:this.value>


<xp:inputText id="inText_${rptIndex}">
<xp:this.defaultValue><![CDATA[#{java script:var a = getComponent("sourceRepeat").getValue();
return a[rptIndex]
}]]></xp:this.defaultValue>
</xp:inputText>

</xp:repeat>
<xp:button value="value 0" id="button2">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="valueRepeat">
<xp:this.action><![CDATA[#{java script:var a = getComponent('inText_0').getValue();

getComponent('valueRepeat').setValue(a)}]]></xp:this.action>
</xp:eventHandler></xp:button><xp:button value="value 1" id="button6">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="valueRepeat">
<xp:this.action><![CDATA[#{java script:var a = getComponent('inText_1').getValue();

getComponent('valueRepeat').setValue(a)}]]></xp:this.action>
</xp:eventHandler></xp:button><xp:button value="value 2" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="valueRepeat">
<xp:this.action><![CDATA[#{java script:var a = getComponent('inText_2').getValue();

getComponent('valueRepeat').setValue(a)}]]></xp:this.action>
</xp:eventHandler></xp:button><xp:button value="value 3" id="button3">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="valueRepeat">
<xp:this.action><![CDATA[#{java script:var a = getComponent('inText_3').getValue();

getComponent('valueRepeat').setValue(a)}]]></xp:this.action>
</xp:eventHandler></xp:button><xp:button value="value 4" id="button4">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="valueRepeat">
<xp:this.action><![CDATA[#{java script:var a = getComponent('inText_4').getValue();

getComponent('valueRepeat').setValue(a)}]]></xp:this.action>
</xp:eventHandler></xp:button>



    <xp:text escape="true" id="valueRepeat" style="color:rgb(0,128,255);font-weight:bold"></xp:text>
</xp:view>


Вообще-то в хэпагах вычисляется всё
 

KingGLEB

Active member
08.05.2008
30
0
BIT
0
Тоже наступил на грабли. :rolleyes:
Не создается нормальный id в repeat, если у repeat не указан repeatControls="true".
Может кому полезно будет.
 

Eugen

Green Team
22.03.2012
210
1
BIT
1
Всем привет. Пытаюсь реализовать похожую конструкцию у себя, а флаг repeatControls портит всю малину...
Кто может подсказать, для чего конкретно он нужен? Хэлп говорит что он типа либо создаст один контрол, либо набор, на каждую итерацию и я не понимаю, что бы это значило...

А вообще у меня проблема вот в чем: хочу сделать вычисляемый id div'ов в репитере, как в примере. Пока у репитера value обычный массив(var arr = ['aa','bb'] например) repeatControls="true" не влияет на отображение.
Как только value становится NotesDocumentCollection - все, div репитера на странице отсутствует. И никаких ошибок/месседжей...
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 933
609
BIT
177
Всем привет. Пытаюсь реализовать похожую конструкцию у себя, а флаг repeatControls портит всю малину...
Кто может подсказать, для чего конкретно он нужен? Хэлп говорит что он типа либо создаст один контрол, либо набор, на каждую итерацию и я не понимаю, что бы это значило...

А вообще у меня проблема вот в чем: хочу сделать вычисляемый id div'ов в репитере, как в примере. Пока у репитера value обычный массив(var arr = ['aa','bb'] например) repeatControls="true" не влияет на отображение.
Как только value становится NotesDocumentCollection - все, div репитера на странице отсутствует. И никаких ошибок/месседжей...
если вопрос получения в клиентском коде - надо через SSJS прокидывать id эелементов
 

Eugen

Green Team
22.03.2012
210
1
BIT
1
если вопрос получения в клиентском коде - надо через SSJS прокидывать id эелементов
Вообще проблема шире. На страницу добавлен репитер. Датасорс для него - NotesViewEntryCollection доков из другой базы(конструкция типа embedded view). На форме есть кнопка, которая позволяет редактировать поля этих отображаемых доков и сохранять изменения(за пределами репитера, но внутри panel). Весь репитер с кнопкой обернут в Panel с заданным датасорс dominoView, на который завязан репитер. Мне нужно кодом из другой кнопки(общая "Сохранить" для всего дока), находящейся за пределами panel либо получить xsp документ каждого дока внутри репитера и сохранить его(со всеми изменениями), либо получить введенные значения и сложить их в целевые документы в бэке.
Либо где-то глобально хранить эту коллекцию в java объекте например... или еще где.
 

NickProstoNick

Статус как статус :)
Lotus Team
22.08.2008
1 851
27
BIT
0
есть такой метод на SSJS
save();
Он постит все документы, которые открыты на странице
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!