XPages save datasource - date not being saved - xpages

I have some curious behavior on an XPage. Would someone be able to shed some light on this?
In my custom control, I have the datasource defined:
<xp:this.data>
<xp:dominoDocument var="incidentDoc" formName="Incident" computeWithForm="onsave" ignoreRequestParams="true">
<xp:this.databaseName><![CDATA[#{javascript:var db = sessionScope.serverPath + "!!" + sessionScope.dbName;
return db;}]]>
</xp:this.databaseName>
</xp:dominoDocument>
</xp:this.data>
Source code for the date field follows. I'm using the eonasdan Bootstrap datepicker.
<div class="col-xs-12 col-md-3 col-lg-3">
<xp:label styleClass="text-muted" value="Date" id="label2"></xp:label>
<br></br>
<div class="form-group">
<div class='input-group date'
id='datetimepicker1'>
<xp:inputText styleClass="form-control"
readonly="true" value="#{incidentDoc.incidentDate}"
id="incidentDate">
<xp:this.attrs>
<xp:attr value="Pick a date"
name="placeholder">
</xp:attr>
</xp:this.attrs>
</xp:inputText>
<span class="input-group-addon">
<i class="zmdi zmdi-calendar"></i>
</span>
</div>
</div>
</div>
<script type="text/javascript">
$(function () {
$('#datetimepicker1').datetimepicker({
format: 'MM/DD/YYYY',
pickTime: false
});
});
</script>
And the call to save the datasource is:
incidentDoc.save();
The incidentDate field in the Notes form is a text field. When I save the datasource, a document gets created with every field on the form populated except the date field.
I've tried setting it to type Date/Time on both the Notes form and the XPage (using the converter) but it does not seem to make a difference. I'm seem to be missing something basic here.
Any thoughts?
Thanks!
Update: Removing readonly="true" seems to do the trick.

Removing readonly="true" seems to do the trick.

Related

Saving radio button selection

I've been playing around with this all day but cannot seem to get it to work the way I want it to :o(
I am writing an application that allows users to select a menu in the canteen. I would like a nice table like this:
The options for the various menus are saved on the document menu which the user selected on the previous screen (listing the week) - this is saved in the data source menu.
The user then selects what s/he wants for that week - they then press save and I need to create a selection document that contains M1, M2 or M3 in the field called Monday (mon), M1, M2 or M3 in the field called Tuesday (tue) etc.
Now matter what I did I could not get the options too line up as I wanted them using what I knew of XPages. I have now ended up with the code below (only added the code for the Monday (Montag) line to give you an idea of what I am doing. The same code is basically repeated for each day of the week (will use a repeat control later down the line). How do I now either 1) attach my XPages field to the variable (as you can see I am using pure BootStrap) or find the value of the selected option in SSJS so I can create a new document using JS?
Any help would be greatly appreciated.
<!-- ======================== Montag ================================== -->
<div class="row">
<div class="row">
<div class="col-md-2">
<xp:text escape="true" id="computedField1">Montag</xp:text>
</div>
<div class="col-md-3">
<label class="radio-inline">
<input type="radio" name="montag" id="Radios1" value="M1">
<xp:text escape="true" id="computedField3">
<xp:this.value><![CDATA[#{javascript:menu.getItemValueString("mon_1");}]]></xp:this.value>
</xp:text>
</input>
</label>
</div>
<div class="col-md-3">
<label class="radio-inline">
<input type="radio" name="montag" id="Radios2" value="M2">
<xp:text escape="true" id="computedField4">
<xp:this.value><![CDATA[#{javascript:menu.getItemValueString("mon_2");}]]></xp:this.value>
</xp:text>
</input>
</label>
</div>
<div class="col-md-3">
<label class="radio-inline">
<input type="radio" name="montag" id="Radios3" value="M3">
<xp:text escape="true" id="computedField5">
<xp:this.value><![CDATA[#{javascript:menu.getItemValueString("mon_3");}]]></xp:this.value>
</xp:text>
</input>
</label>
</div>
</div>
</div>
changes suggested by Mark:
here the image:
[]
and the code:
<div class="col-md-3">
<label class="radio-inline">
<xp:radio id="Radios1" groupName="mon" value="#{wahl.mon}">
<xp:text escape="true" id="computedField3">
<xp:this.value><![CDATA[#{javascript:menu.getItemValueString("mon_1");}]]></xp:this.value>
</xp:text>
</xp:radio>
</label>
</div>
<div class="col-md-3">
<label class="radio-inline">
<xp:radio id="Radios2" groupName="mon" value="#{wahl.mon}">
<xp:text escape="true" id="computedField4">
<xp:this.value><![CDATA[#{javascript:menu.getItemValueString("mon_2");}]]></xp:this.value>
</xp:text>
</xp:radio>
</label>
</div>
<div class="col-md-3">
<label class="radio-inline">
<xp:radio id="Radios3" groupName="mon" value="#{wahl.mon}">
<xp:text escape="true" id="computedField5">
<xp:this.value><![CDATA[#{javascript:menu.getItemValueString("mon_3");}]]></xp:this.value>
</xp:text>
</xp:radio>
</label>
</div>
If you set up the radio buttons like this, they render according to the specs. Note that I've added a binding to a viewScope parameter.
<div
class="col-md-3">
<xp:radio
text="option 1"
disableTheme="true"
styleClass="radio-inline"
id="radio1"
selectedValue="M1"
groupName="montag"
value="#{viewScope.montagSelected}">
</xp:radio>
</div>
It generates the following HTML (I'm using the default 'Bootstrap3' theme):
<div class="col-md-3">
<label
for="view:_id1:radio1"
class="radio-inline">
<input id="view:_id1:radio1"
type="radio"
name="view:_id1:montag"
value="M1"
onchangetrigger="early-onclick">
option 1
</label>
</div>

read value editbox in ssjs in a custom control

I have a custom control with an editbox in a modal:
<xp:inputText id="inputText1"></xp:inputText>
In the onclick event of a button , I would like to read the value of this editbox
var demo = getComponent("inputText1").getValue();
Of course this doesn't work in a custom control, since he doesn't has a handle to inputText1. How can this be done ?
EDIT
Herewith I'm posting my 'whole' code.
Even with a scoped variable it isn't working .... :(
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.resources>
<xp:styleSheet href="bootstrap-modal.css"></xp:styleSheet>
<xp:script src="/bootstrap-modalmanager.js" clientSide="true"></xp:script>
<xp:script src="/bootstrap-modal.js" clientSide="true"></xp:script>
<xp:script src="/JQueryXSnippet.js" clientSide="true"></xp:script>
</xp:this.resources>
<div id="Modal1" class="modal fade" tabindex="-1" data-focus-on="input:first" style="display: none;">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Modal One</h4>
</div>
<div class="modal-body">
<p>Modal 1 </p>
<div class="form-group">
<label for="inputText1">First Name:</label>
<xp:inputText id="inputText1" value="#{viewScope.input1}">
<xp:this.attrs>
<xp:attr name="class" value="form-control"></xp:attr>
<xp:attr name="data-tabindex" value="1"></xp:attr>
</xp:this.attrs>
</xp:inputText>
</div>
<xp:button value="Demo" id="button2">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="demoPanel">
<xp:this.action><![CDATA[#{javascript:viewScope.message = "input1 = "+viewScope.input1;}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:panel id="demoPanel">
<xp:text escape="true" id="computedField1"
value="#{viewScope.message}">
</xp:text>
</xp:panel>
</div>
<div class="modal-footer">
<button type="button" data-dismiss="modal" class="btn btn-primary">Close</button>
</div>
</div>
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
$(document).ready(function(){
x$("#{id:button1}").click(function(){
x$("#{id:Modal1}").modal(
{backdrop: true,
keyboard: false,
show: true
}
);
});
});
]]></xp:this.value>
</xp:scriptBlock>
<xp:button value="Login" id="button1" styleClass="btn btn-info btn-lg">
</xp:button>
</xp:view>
The advice from Tim Tripcony was to go to the model layer, not the component. As ever, he was spot on. Bind the Edit Box to something, probably in this scenario a viewScope variable. Then retrieve the value from that. It's likely to be more efficient than getComponent().
There are two ways that spring to mind are worth trying:
Add the button to the custom control and that way, it'll just work as is.
Set the id to be computed from a custom property of the control control-id and pass in a string e.g. my-made-up-id and then refer to it from any button out-with the custom control. Note the ${} binding is needed when computing the id.
Custom Control
<xp:inputText
id="${javascript:compositeData.control-id}">
</xp:inputText>
XPage
<xc:FieldTest control-id="my-made-up-id"></xc:FieldTest>
<xp:button
value="Get Value"
id="button1">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:var demo = getComponent("my-made-up-id").getValue();
print("Demo: " + demo);}]]></xp:this.action>
</xp:eventHandler>
</xp:button>

Date fields and BootStrap Extension Lib

I have a very simple form that I am trying to use BootStrap from the ExtLib with. Everything is fine until I add a field that is of type Date or Time. Any fields after that field are then off in the design. I would like the labels on the left and the fields on the right. As you can see in this example the "von" and "bis" fields are off once the "Datum" field is displayed (yes, I do see that "Jause" and "Mittagessen" are not aligned correctly, I'll see what the problem is there later :) I have tried everything but cannot see my mistake.
Here is what I am getting in Chrome:
And here is the code:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:panel>
<xp:this.data>
<xp:dominoDocument var="document1" formName="fmTermin"></xp:dominoDocument>
</xp:this.data>
<div class="panel panel-default">
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">Mitarbeiter_in</label>
<div class="col-sm-10">
<p class="form-control-static">
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:context.getUser().getFullName()}]]></xp:this.value>
</xp:text>
</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Standort</label>
<div class="col-sm-10">
<p class="form-control-static">
<xp:text escape="true" id="computedField2">
<xp:this.value><![CDATA[#{javascript:userName = context.getUser().getFullName();
#DbLookup(#DbName(), "vwMitarbeiterInNachStandort", userName, 2)}]]></xp:this.value>
</xp:text>
</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Kind</label>
<div class="col-sm-10">
<p class="form-control-static">
<xp:comboBox id="comboBox1" value="#{document1.nachname}" style="width:350px">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:userName = context.getUser().getFullName();
standort = #DbLookup(#DbName(), "vwMitarbeiterInNachStandort", userName, 2);
kinder = #DbLookup(#DbName(), "vwKindNachStandort", standort, 2);
kinder
}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Jause</label>
<div class="col-sm-10">
<xp:checkBox text="Jause" id="checkBox1" value="#{document1.Jause}" checkedValue="1" uncheckedValue="0"
defaultChecked="true"
></xp:checkBox>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Mittagessen</label>
<div class="col-sm-10">
<xp:checkBox text="Mittagessen" id="checkBox2" value="#{document1.mittagessen}" checkedValue="1" uncheckedValue="0"
defaultChecked="true">
</xp:checkBox>
</div>
</div>
<div class="form-group">
<xp:label value="Datum" id="label1" for="datum" styleClass="control-label col-sm-2">
</xp:label>
<div class="col-sm-10">
<xp:inputText id="datum" value="#{document1.datum}" defaultValue="#{javascript:#Now()}">
<xp:dateTimeHelper></xp:dateTimeHelper>
<xp:this.converter>
<xp:convertDateTime type="date" dateStyle="short"></xp:convertDateTime>
</xp:this.converter>
</xp:inputText>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Von</label>
<div class="col-sm-10">
<xp:inputText id="von" value="#{document1.von}" defaultValue="#{javascript:#Now()}">
<xp:dateTimeHelper></xp:dateTimeHelper>
<xp:this.converter>
<xp:convertDateTime type="time" timeStyle="short"></xp:convertDateTime>
</xp:this.converter>
</xp:inputText>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Bis</label>
<div class="col-sm-10">
<xp:inputText id="bis" value="#{document1.bis}" defaultValue="#{javascript:#Now()}">
<xp:dateTimeHelper></xp:dateTimeHelper>
<xp:this.converter>
<xp:convertDateTime type="time" timeStyle="short"></xp:convertDateTime>
</xp:this.converter>
</xp:inputText>
</div>
</div>
</form>
</div>
</div>
</xp:panel>
</xp:view>
I've copied your code and tested it with version 11 of the Extension Library and the built-in Bootstrap3.2.0 theme. I've changed the <form class="form-horizontal"> to a <div class="form-horizontal">. After that it looked Ok: Von und Bis were rendered just as the other labels.
A <form> is always created by the XPages engine automatically, so you don't need to add that yourself. The form-horizontal class in Bootstrap isn't restricted for use with a form tag only: it can be used just as well with a <div>.
Mark answered the question but I cannot seem to find the "Mark as Answered" flag in the comment! Here is his answer:
I've copied your code and tested it with v11 of the ExtLib and the built-in Bootstrap3.2.0 theme. I've changed the to a . Adding your own form tags to an XPage isn't a good idea. After that it looked Ok: Von und Bis were rendered just as the other labels

Required Date Time Picker has always "aria-invalid=false"

I'm not sure if I am missing out a very simple thing. Normally, XPages maintain "aria-required" and "aria-invalid" attributes for validation.
However, for DateTime Picker (standard one), it's always aria-invalid="false".
Here is a simple test I have used in Domino 9.0.1:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.data>
<xp:dominoDocument var="document1" formName="TestForm"></xp:dominoDocument>
</xp:this.data>
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="panel1">
</xp:eventHandler>
</xp:button>
<xp:panel id="panel1">
<xp:inputText id="inputText1" required="true">
<xp:dateTimeHelper id="dateTimeHelper1"></xp:dateTimeHelper>
<xp:this.converter>
<xp:convertDateTime type="date"></xp:convertDateTime>
</xp:this.converter>
</xp:inputText>
<xp:messages id="messages1"></xp:messages>
</xp:panel>
</xp:view>
Generated HTML before the button clicked contains:
<input type="text" aria-haspopup="true" role="textbox" data-dojo-attach-point="textbox,focusNode" autocomplete="off" class="dijitReset dijitInputInner" aria-invalid="false" tabindex="0" aria-required="true" id="view:_id1:inputText1" value="">
After clicking, I can see Messages component has been aggregated but aria-invalid is false.
<input type="text" aria-haspopup="true" role="textbox" data-dojo-attach-point="textbox,focusNode" autocomplete="off" class="dijitReset dijitInputInner" aria-invalid="false" tabindex="0" aria-required="true" id="view:_id1:inputText1" value="">
(I removed dojo stuff wrapping the input)
After some digging, I found that this problem is not related to XPages.
XPages provides the aria-invalid attribute correctly if validation fails. However, dojo controls automatically change it during rendering. So it's not possible unless you inject a correction into Dojo component rendering code.

Xpages Date Time Picker field defaults to today's date

Running a ND9 server and when browsing a Xpage with a date field, the default value for this field is always today's date.
On a 8.5.3 server the control is rendered like this:
<input class="dijitReset dijitInputInner" dojoattachpoint="textbox,focusNode" autocomplete="off" type="text" aria-valuenow="undefined" aria-invalid="false" id="view:_id1:_id2:main:fromTDate" tabindex="0" value="">
<input style="display: none;" type="text" name="view:_id1:_id2:main:fromTDate">
On a ND9 server the same control renders like this:
<input class="dijitReset dijitInputInner" type="text" autocomplete="off" data-dojo-attach-point="textbox,focusNode" role="textbox" aria-haspopup="true" aria-invalid="false" tabindex="0" id="view:_id1:_id2:main:fromTDate" maxlength="10" size="10" value="">
<input type="hidden" name="view:_id1:_id2:main:fromTDate" value="2013-03-26">
I've been able to circumvent it by adding a Dojo Date Text Box instead but this feature must be wrong, right?
This was actually a fix put into v9.0. Today's date appearing by default is now the expected behaviour
Add this to your XPage and the behavior is like in 8.5.3
<xp:this.resources>
<xp:script clientSide="true">
<xp:this.contents><![CDATA[
require([
"dojo/_base/lang",
"ibm/xsp/widget/layout/DateTextBox",
"ibm/xsp/widget/layout/TimeTextBox",
"ibm/xsp/widget/layout/DateTimeTextBox"
], function(lang, DateTextBox, TimeTextBox, DateTimeTextBox){
var a = {};
lang.mixin(a, {
postCreate: function(){
this.inherited(arguments);
}
});
DateTextBox.extend(a);
TimeTextBox.extend(a);
DateTimeTextBox.extend(a);
});
]]></xp:this.contents>
</xp:script>
</xp:this.resources>
Thanks IBM for the fast response.

Resources