Frage

I would like to add a custom-control via SSJS, just like I can add a component ("Component Tree Injection" http://openntf.org/XSnippets.nsf/snippet.xsp?id=component-tree-injection) but I cannot get it to work.

I want to build a "New Person" button on a page, which adds a Custom-Control every time the user clicks on it.

First I tried to accomplish that via a RepeatControl using repeatControl="true", but that was not possible because I cannot afford to reload the whole Xpage in order to create the new CCs and losing all the other data in that process. (See code-block)

Should you know of any other possibility to add a custom-control dynamically without reloading the page please feel free to explain. ;-)

Thanks a lot!

<xp:button value="New Person" id="newPersonButton">
    <xp:eventHandler event="onclick" submit="true" refreshMode="complete">
        <xp:this.action>
            <![CDATA[#{javascript://
                viewScope.counter = viewScope.counter + 1;
            }]]>
        </xp:this.action>
    </xp:eventHandler>
</xp:button>
<xp:repeat id="repeat1" rows="30" repeatControls="true" var="rowData" indexVar="rowIndex">
    <xp:this.value><![CDATA[#{javascript:return new Array(Number(viewScope.counter))}]]></xp:this.value>
    <xc:ccPersondata id="persondata_${rowIndex}"></xc:ccPersondata>
</xp:repeat>

Solution: For the final solution i combined the answer from Michal Saiz ( You just made my day! :) ) with Dynamically bind an Edit Box in a custom control to a managed bean and came up with the following code:

XPage

<xp:repeat id="repeat1" rows="30" var="rowData" indexVar="rowIndex">
    <xp:this.value><![CDATA[#{javascript://
    var person = function(name,age){
        this.name = name;
        this.age = age;
    }
    if(!viewScope.containsKey('list')){
        viewScope.list = [];
        list.push(new person("victor","24"));
        list.push(new person("Igor","24"));
    }
    return viewScope.list;}]]></xp:this.value>
    <xp:panel>
        <xc:ccPersondata id="ccPersondata" BindTo="rowData" />          
    </xp:panel>
</xp:repeat>
<xp:button value="addPerson" id="button1">
    <xp:eventHandler event="onclick" submit="true" refreshMode="complete">
        <xp:this.action><![CDATA[#{javascript:
    var person = function(name,age){
        this.name = name;
        this.age = age;
    }
    var emptyPerson = new person('none','0');
    viewScope.list.push(emptyPerson);}]]></xp:this.action>
    </xp:eventHandler>
</xp:button>

Custom-Control: ccPersondata

<xp:label value="Name:" id="label1">
    <xp:inputText id="name">
        <xp:this.value><![CDATA[${javascript:"#{"+compositeData.BindTo+".name}"}]]></xp:this.value>
    </xp:inputText>
</xp:label>
<xp:label value="Age:" id="label2">
    <xp:inputText id="age">
        <xp:this.value><![CDATA[${javascript:"#{"+compositeData.BindTo+".age}"}]]></xp:this.value>
    </xp:inputText>
</xp:label>
War es hilfreich?

Lösung

Why adding a custom control manual if you already have a repeat control wich can create any number of of ccPersondata. Instead of adding a control manual by using component injection i would just add another empty value to your repeated Array (like a empty Person object/Array whatever you are using to hold the person's data) and refresh the repeat control.

Here a small example what i mean:

<xp:repeat id="repeat1" rows="30" var="rowData" indexVar="rowIndex">
    <xp:this.value><![CDATA[#{javascript://
        var person = function(name,age){
            this.name = name;
            this.age = age;
        }
        if(!viewScope.containsKey('list')){
            viewScope.list = [];
            list.push(new person("victor","24"));
            list.push(new person("Igor","24"));
        }
        return viewScope.list;}]]></xp:this.value>
        <xp:panel>
            <xp:text
                escape="true"
                id="computedField1"
                value="#{rowData.name}">
            </xp:text>
            <br></br>
                                <!-- here is your ccPersonData -->
    </xp:panel>
</xp:repeat>
<xp:button value="addPerson" id="button1">
<xp:eventHandler
    event="onclick" submit="true" refreshMode="partial" refreshId="repeat1">
    <xp:this.action><![CDATA[#{javascript:
        var person = function(name,age){
            this.name = name;
            this.age = age;
        }
        var emptyPerson = new person('none','0');
        viewScope.list.push(emptyPerson);}]]></xp:this.action>
</xp:eventHandler>
</xp:button>

In your case instead of the SSJS Objects i would use a java class or documents depending on your needs. Also i would use a java class wich handles the data for the repeat so you can handle the functions (new persons, or save Person) with this class.. maby including a method addPersonOnPsoition()....

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top