I'm trying and trying for some time to resolve a viewPanel functionality - var property set to rowData.
Depending on the form name, I want to open the docs. ( which are listed in my viewPanel ) in a normal way and into a <xe:dialog> control. I did found this question Xpages Dynamic dojo dialog control and I'm trying to make it works in my case. the docs which I want to be open in the <xe:dialog>, are also created inside the dialog. By this viewpanel, I want to show/open them using this viewPanel control.
Here is the code from the onClick column event:
var formName = rowData.getDocument().getItemValueString("Form");
var docUNID = rowData.getDocument().getUniversalID();
var href = facesContext.getExternalContext().getRequest().getContextPath();
var pe:NotesViewEntry = rowData
if ( formName == "fmCompanie") // in this case, it works OK.
{ href + "/doc.xsp?documentId=" + docUNID + "&action=openDocument"; }
else if ( formName == "fmPersContact" ) // hmm... Still trying...
{ viewScope.put("dlgDocUnid", pe.getUniversalID())
getComponent("exampleDialog").show(); }
So, by this event I'm trying to set a viewScope variable which uses the UNID for the datasource in my exampleDialog control.
Also: the dialog control ( which lays on the same custom control as the viewPanel) has the documentId:
<xp:this.data>
<xp:dominoDocument var="Pdoc" formName="fmPersContact"
ignoreRequestParams="true" scope="request">
<xp:this.documentId><![CDATA[#{javascript:viewScope.get("dlgDocUnid");}]]></xp:this.documentId>
</xp:dominoDocument>
</xp:this.data>
Still, when I'm trying to open a doc. ( using form == "fmPersContact") the dialog has all fields empty, even if the doc. is already fill with some field values.
I appreciate your help. Thanks for your time.
The data source in the dialog does not contain action attribute. Therefore it does not respect the documentId parameter and creating a new document within the dialog.
Add action="editDocument" attribute and it will work.
Also, check what you are refreshing with the onclick event. You should partially refresh an area that contains your data (e.g. dialog or the panel in your dialog, etc.)
Related
On an custom control I have data-source bounded to a panel control:
<xp:panel>
<xp:this.data>
<xp:dominoDocument var="attachDoc" formName="fAttachment"></xp:dominoDocument>
</xp:this.data>
...
</xp:panel>
Within the panel I have some Edit Box controls e.g.
<xp:inputText id="inpOfficial" value="#{attachDoc.migration}">
When I try to save the doc via SSJS the edit boxes are not saved:
function saveAttachment(){
try {
var doc:NotesDocument = attachDoc.getDocument();
doc.save();
}
}
What am I missing?
The custom control is repeated over the xpage. The custom control has it's own save button calling the saveAttachment() function
Your saveAttachment() function appears to be trying to save a back end notes document on the database. To pass through the changes in the UI you need to run attachDoc.save() which passes the NotesXSPDocument (UI doc) through to the back end NotesDocument saved to the database.
(Assuming your try statement has a catch but you've left that out)
https://www.ibm.com/support/knowledgecenter/en/SSVRGU_9.0.1/reference/r_wpdr_xsp_xspdocument_r.html
Andrew Norrie is right.
If you still wish to use the back-end NotesDocument, get it like this:
var doc:NotesDocument = attachDoc.getDocument(true);
The parameterized getDocument method will update the back-end NotesDocument with the model values before return.
My app uses KendoUI Grids for user views, but Xpages with custom controls for form pages (at least for now).
The Xpage looks for a sessionScope variable to determine if it is a new doc (nothing in the scope Var) or and update (unid is in the var).
<xp:this.data>
<xe:objectData
saveObject="#{javascript:PCModel.save()}"
var="PCModel">
<xe:this.createObject><![CDATA[#{javascript:var pc = new com.scoular.model.PC();
var unid = sessionScope.get("key");
if (unid != null) {
pc.loadByUnid(unid);
sessionScope.put("key","");
viewScope.put("readOnly","Yes");
} else {
pc.create();
viewScope.put("readOnly","No");
}
viewScope.status = pc.status;
return pc;}]]></xe:this.createObject>
</xe:objectData>
</xp:this.data>
This worked for a completely Xpage app. I just put a value in the sessionScope key and called the Xpage.
In the Kendo UI code I am using client-side javascript and I don't see a way to set the sessionScope.
I can control the URL, so I could switch gears and use that, however the data for my app is in a different DB than my code.
Any help would be greatly appreciated.
The easiest way is indeed using the URL:
call the XPage with a parameter ?key=... and change your CSJS code line to
var unid = param.key;
In case you really need to set a sessionScope variable from client side
then add this empty computed text field
<xp:text
escape="true"
id="setSessionScope"
value="#{javascript: if (param.key) {sessionScope.key = param.key} ''}" />
to your XPage and set the sessionScope variable in CSJS code with
XSP.partialRefreshGet("#{id:setSessionScope}", {params: {'key': 'your key'}})
In a previous post I asked how to add a bootstrap class to a Data View. The answer was to add the class to the "table.dataview" in a script block. After the table is created the class is applied and all is well.
But when I use a pager the formatting disappears. I am using a partial refresh on the pager to only refresh the data table but doing so means that the bootstrap class does not get applied to the table.
I believe I need to add an event handler that will attach to the refresh action of the dataView to add the class. However I cannot get the event handler to work.
My code for the event handler is below.
<xp:eventHandler refreshMode="partial" submit="true"
id="applyCSS" refreshId="dataView1" event="parialRefresh"
value="what" loaded="false">
<xp:this.binding><![CDATA[#{javascript:"pager1"}]]></xp:this.binding>
<xp:this.action><![CDATA[#{javascript:("table.dataview").addClass("table-striped table-hover table-bordered table-condensed")}]]></xp:this.action>
</xp:eventHandler>
Oliver, the rendered=false was simply a typo - I was testing something and needed to temporarily suppress that.
Oliver and Paul,
Last night I was able to get the partial refresh to work.
I ran across this post by Mark Roden which explained how to do it. There were two different ways to accomplish this, one less and one more efficient. The code I used is below.
<xp:scriptBlock id="scriptBlock3">
<xp:this.value><![CDATA[$('.dataView1PanelWrapper').on("DOMNodeInserted", function(){
$("table.dataview").addClass("table-striped table-hover table-bordered table-condensed")
})]]></xp:this.value>
</xp:scriptBlock>
However, and isn't there almost always a however in Xpages, I have some sortable columns in the view and clicking on the sort brings up the same problem! I lose the class assignment!
So now I would have to intercept that event too, right?
Concerned where this will end. Don't like the idea of DOM Manipulation, and only want to do it if I have too.
I started by using a simple view. It worked great, but for some reason the spacing was messed up in the pagers. I found that by moving the pagers out of the view itself, I was able to get the alignment issue fixed. I think it would be better just to use a view, as I can assign the class directly and won't have to do all this manipulation. It is however very good to know how to do this for the future.
Is that what you would suggest?
==================================================
I have tried Paul Withers suggestion using an output script. This works on the initial page load, but not on any other changes to the data view - when the pager fires, or sorting or any of that. I am close, but no cigar yet. Any suggestions?
<xp:scriptBlock id="scriptBlock5" loaded="false">
<xp:this.value><![CDATA[dojo.require("dojo.behavior");
Behavior = {
".dataview": {
found: function(node) {
dojo.addClass(node,".table-striped table-hover table-bordered table-condensed");
//node.addClass("table-striped table-hover table-bordered table-condensed");
}
}
}
dojo.ready(function() {
dojo.behavior.add(Behavior);
dojo.behavior.apply();
});
//Make sure that future pagers are also straightened out
dojo.subscribe("partialrefresh-complete", null, function(method, form, refreshId) {
dojo.behavior.apply();
});]]></xp:this.value>
</xp:scriptBlock>
Move your existing xp:scriptBlock with the working code inside a facet of the xe:dataView. Then the styling will get applied on initial load and on all partial refreshes.
You should call your CSJS stuff to add the class in the onComplete property of the event handler - hard to find, just highlight the event handler object in source code or outline and then open "All properties" to find the "onComplete" property. This event allows CSJS to be called.
BTW: why is the loaded property = false? The event will never we rendered.
dojo.behavior, dojo.ready and dojo.subscribe should allow you to manage this. dojo.behavior allows you to define a particular behaviour for a particular collection of elements which will be retrieved via a Dojo query. dojo.ready will (I believe) run the code when the page initially loads and dojo.subscribe("partialrefresh-complete", null, function(method, form, refreshId) {...} will run the code aftedr a partial refresh.
Here's sample code I used for converting a DataView's category column images to Font Awesome icons, so the Behavior = {...} bit will need amending.
Behavior = {
// Convert xp:pagers to Bootstrap
".catColumn a img": {
found: function(img_node) {
var imgSrc = dojo.getNodeProp(img_node, "alt").toLowerCase();
if (imgSrc.indexOf("collapse") >= 0) {
dojo.place('<i class="fa fa-minus-square"></i> ', img_node, 'replace');
} else {
dojo.place('<i class="fa fa-plus-square"></i> ', img_node, 'replace');
}
}
}
}
dojo.ready(function() {
dojo.behavior.add(Behavior);
dojo.behavior.apply();
});
//Make sure that future pagers are also straightened out
dojo.subscribe("partialrefresh-complete", null, function(method, form, refreshId) {
dojo.behavior.apply();
});
I'm trying to find a way to open the Extension Library Value Picker automatically after load of my XPage. I tried putting the following in the onClientLoad event:
dojo.byId('#{id:MyValuePicker}').click();
But it appears that the value picker does not have a click() method to open the dialog. Any ideas are appreciated. Thanks.
EDIT: Changed code based on #stwissel's comment and viewid issue:
Put the folloiwng in a scriptBlock:
<xp:scriptBlock>
<xp:this.value><![CDATA[
var viewID = "#{javascript:viewScope.viewID}";
XSP.selectValue('extlib.dijit.PickerList',{
"msep":",",
"trim":true,
"listWidth":"550px",
"dlgTitle":"Select One Or More Values",
"control":"#{id:BoundControl}",
"url":"\/Database.nsf\/Test.xsp?$$viewid="+viewID+"&$$axtarget=#{id:MyValuePicker}"
})
]]>
</xp:this.value>
</xp:scriptBlock>
The viewID is set in the beforePageLoad event:
viewScope.viewID = com.ibm.xsp.application.UniqueViewIdManager.getUniqueViewId(facesContext.getViewRoot())
to get this working with bootstrap, use extlib.dijit.BootstrapPickerList3.
Or much better is 'extlib.responsive.dijit.xsp.bootstrap.PickerList'
I have a computed field on an xpage the result of which is HTML. In that HTML I want to compute a link that will trigger some server side js function followed by a partial refresh.
My current code looks like this:
Click Here
This will work if my js function is a client-side function but I want to use this function to set the value of a field on the document so I need SSJS.
Static links that are created from the controls pallet in an xpage allow the link to call SSJS with partial refreshes. How can I do this with a computed HTML link?
Another option could be creating your own event handler and executing that via client side JavaScript code described in this article. So suppose you create an event handler something like this:
<xp:eventHandler event="name" id="eventhandler1a">
<xp:this.action>
<xp:saveDocument />
</xp:this.action>
</xp:eventHandler>
You can then create a function to call this event handler via JavaScript code:
XSP.executeOnServer = function () {
// the event handler id to be executed is the first argument, and is required
if (!arguments[0])
return false;
var functionName = arguments[0];
// OPTIONAL - The Client Side ID that is partially refreshed after executing the event handler
var refreshId = (arguments[1]) ? arguments[1] : "#none";
var form = (arguments[1]) ? this.findForm(arguments[1]) : dojo.query('form')[0];
// catch all in case dojo element has moved object outside of form...
if (!form)
form = dojo.query('form')[0];
// OPTIONAL - Options object containing onStart, onComplete and onError functions for the call to the
// handler and subsequent partial refresh
var options = (arguments[2]) ? arguments[2] : {};
// OPTIONAL - Value to submit in $$xspsubmitvalue. can be retrieved using context.getSubmittedValue()
var submitValue = (arguments[3]) ? arguments[3] : '';
// Set the ID in $$xspsubmitid of the event handler to execute
dojo.query('[name="$$xspsubmitid"]')[0].value = functionName;
dojo.query('[name="$$xspsubmitvalue"]')[0].value = submitValue;
this._partialRefresh("post", form, refreshId, options);
}
You can then call the event handler via this client side JavaScript code:
XSP.executeOnServer('#{id:eventhandler1a}', '#{id:panel1}')
Here panel1 refers to control which would be partially refreshed.
You can stick with your code if you use the XSP Object in the myFunction() client side function. This allows you to call a partial refresh. The other option is to call a Extlib JSON control and have your logic there. Depends a little on your coding style
The link control is not static. You can compute whatever you want, for example:
<xp:link escape="true" id="lnk">
<xp:this.value><![CDATA[#{javascript:"#"}]]></xp:this.value>
<xp:this.text><![CDATA[#{javascript:"Label here"}]]></xp:this.text>
</xp:link>