admin管理员组文章数量:1279209
I am adding in a new item into a repeat. I want to focus in on the first input field of the newly inserted entry. If I use 'setfocus' with the 'control' set to the repeat id itself - nothing happens. If I instead set the 'id' of my entry to 'fname' (in this example) and then call 'setfocus' with control set to 'fname' - the focus is shifted to the first item in the repeat.
I wasn't able to use AVTs to generate a unique ID attribute from within the repeat (the input isn't ever shown if I do that).
Any advice on how to achieve this?
<?xml-stylesheet href="xsltforms/xsltforms.xsl" type="text/xsl"?>
<html
xmlns=";
xmlns:xs=";
xmlns:xf=";
xmlns:ev="; lang="en">
<head>
<xf:model id="model">
<xf:instance id="data">
<data xmlns="">
<rows>
<row>
<fname>joe</fname>
<lname>bloggs</lname>
</row>
</rows>
</data>
</xf:instance>
</xf:model>
</head>
<body>
<h1> Focus Test </h1>
<xf:output value="index('r1')"/>
<xf:repeat id="r1" ref="instance('data')/rows/row">
<xf:input id="fname" ref="fname"/>
<xf:input ref="lname"/>
</xf:repeat>
<xf:trigger>
<xf:label>+</xf:label>
<xf:action ev:event="DOMActivate">
<xf:insert origin="instance('data')/rows/row[last()]" ref="instance('data')/rows/row"/>
<xf:setvalue ref="instance('data')/rows/row[last()]/fname"/>
<xf:setvalue ref="instance('data')/rows/row[last()]/lname"/>
<xf:setfocus control="fname"/>
</xf:action>
</xf:trigger>
</body>
</html>
I am adding in a new item into a repeat. I want to focus in on the first input field of the newly inserted entry. If I use 'setfocus' with the 'control' set to the repeat id itself - nothing happens. If I instead set the 'id' of my entry to 'fname' (in this example) and then call 'setfocus' with control set to 'fname' - the focus is shifted to the first item in the repeat.
I wasn't able to use AVTs to generate a unique ID attribute from within the repeat (the input isn't ever shown if I do that).
Any advice on how to achieve this?
<?xml-stylesheet href="xsltforms/xsltforms.xsl" type="text/xsl"?>
<html
xmlns="http://www.w3./1999/xhtml"
xmlns:xs="http://www.w3./2001/XMLSchema"
xmlns:xf="http://www.w3./2002/xforms"
xmlns:ev="http://www.w3./2001/xml-events" lang="en">
<head>
<xf:model id="model">
<xf:instance id="data">
<data xmlns="">
<rows>
<row>
<fname>joe</fname>
<lname>bloggs</lname>
</row>
</rows>
</data>
</xf:instance>
</xf:model>
</head>
<body>
<h1> Focus Test </h1>
<xf:output value="index('r1')"/>
<xf:repeat id="r1" ref="instance('data')/rows/row">
<xf:input id="fname" ref="fname"/>
<xf:input ref="lname"/>
</xf:repeat>
<xf:trigger>
<xf:label>+</xf:label>
<xf:action ev:event="DOMActivate">
<xf:insert origin="instance('data')/rows/row[last()]" ref="instance('data')/rows/row"/>
<xf:setvalue ref="instance('data')/rows/row[last()]/fname"/>
<xf:setvalue ref="instance('data')/rows/row[last()]/lname"/>
<xf:setfocus control="fname"/>
</xf:action>
</xf:trigger>
</body>
</html>
Share
Improve this question
edited Feb 23 at 21:59
jonrsharpe
122k30 gold badges267 silver badges474 bronze badges
asked Feb 23 at 21:53
monojohnnymonojohnny
6,19116 gold badges64 silver badges86 bronze badges
2 Answers
Reset to default 1The XForms specification says that
the current index of the
repeat
determines the set of run-time objects that contains the desired target object.
The "set of run-time objects" is the set of controls in one row of your table. So if the index (which is shown above your table) is 2, the xf:setfocus
should target the control corresponding to fname
in the second row.
Apparently XSLTForms does not implement it that way. After the xf:insert
and xf:setvalue
actions, the index becomes 2, but xf:setfocus
always targets the control in the first row and also resets the index to 1. Moreover, for the target to be chosen from the second row, the implementation of the xf:setfocus
action would have to run after that row is created, that is, wait until after the xforms-refresh
event. But it runs much earlier.
A workaround is as follows: Do not execute an xf:setfocus
function (which dispatches a synchronous xforms-focus
event on the target control). Instead, dispatch a custom event setfocus
asynchronously (with delay="1"
) so that it runs after xforms-refresh
:
<xf:trigger>
<xf:label>+</xf:label>
<xf:action ev:event="DOMActivate">
<xf:insert origin="instance('data')/rows/row[last()]"
ref="instance('data')/rows/row"/>
<xf:setvalue ref="instance('data')/rows/row[last()]/fname"/>
<xf:setvalue ref="instance('data')/rows/row[last()]/lname"/>
<xf:dispatch name="setfocus" targetid="fname" delay="1"/>
</xf:action>
</xf:trigger>
And include the definition of this event and its Javascript handler in a <script>
element in the <head>
:
XsltForms_xmlevents.define("setfocus", true, true, function(event) {
let repeat = event.target;
while (!repeat.classList.contains("xforms-repeat"))
repeat = repeat.parentElement;
XsltForms_xmlevents.dispatch(
repeat.querySelectorAll(".xforms-repeat-item")
.item(repeat.xfElement.index - 1)
.querySelector(`[oldid=${event.target.id}]`),
"xforms-focus");
});
This implementation
- moves up from the event target to the
<div class="xforms-repeat">
that wraps the entirerepeat
- looks up the
repeat
's current index (repeat.xfElement.index
) - selects from the row (
<div class="xforms-repeat-item">
) with that index the control that corresponds to the event target ID. The correspondence is maintained by XSLTForms through anoldid
attribute in the controls in all rows (<span oldid="fname">
in this example). - An
xforms-focus
event is then dispatched on the selected control.
This makes the simplifying assumption that the event target is only contained in one repeat
. The general case of nested repeat
s must look up the current index of each of them.
Based on the post from Heiko Theißen.
For this particular case at least - I didn't need to introduce a Javascript function - I just added the following action in my model section:
<xf:model id="model">
...
<xf:action ev:event="setfocus">
<xf:setfocus control="fname"/>
</xf:action>
...
</xf:model>
And dispatched to the custom event with a delay as suggested.
<xf:action ev:event="DOMActivate">
<xf:insert origin="instance('data')/rows/row[last()]" ref="instance('data')/rows/row"/>
<xf:setvalue ref="instance('data')/rows/row[last()]/fname"/>
<xf:setvalue ref="instance('data')/rows/row[last()]/lname"/>
<xf:dispatch name="setfocus" targetid="model" delay="1"/>
</xf:action>
本文标签: xformsHow to set focus to an input within a repeatStack Overflow
版权声明:本文标题:xforms - How to set focus to an input within a repeat? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741301109a2371092.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论