I am using a reponsive grid which is an extension of primefaces. However I can't seem to figure out how to get the index of items within the grid.
I tried rowIndexVar and rowKeyVar and they don't seem to work. I've included a snippet of my code below.
<pe:fluidGrid value="#{resultList}" var="showvar" rowKeyVar="rowKey" fitWidth="true" hasImages="true">
...
</pe:fluidGrid >
...
<h:link onclick="$(callme('#{showvar.showId}','#{rowKey}'));">
<h:graphicImage url="#{showvar.showImage}"/>
</h:link>
....
<h:outputScript>
function callme(id,row){
alert(id);
alert(row);
}
</h:outputScript>
I could just declare an unique index variable in my object and reference it like below, but I'd like to know if fluidGird offers a rowKeyVar attribute.
<ui:param name="itemIndex" value="#{showvar.showIndex}" />
I think what you are looking for is the varContainerId
varContainerId
Name of the request-scoped variable which contains the prefix of the client Id within pe:fluidGridItem. This property allows to get the whole clientId of a component within pe:dynaFormControl. The whole client Id is sometimes required for JavaScript or RequestContext.update(...).
See also: http://www.primefaces.org/showcase-ext/views/fluidGrid.jsf
Related
I'm having a bit of an issue here. I had a small amount of success with event.target.templateInstance.model.thing syntax to get the value of attributes from within a repeating template but I keep getting back undefined from this bit of code I have here:
downloadFunction: function (e) {
console.log("dl function clicked");
//get particular id of thing
var fu = e.target.templateInstance.model.s.soundId;
console.log(fu);
//^ returns "TypeError: Cannot read property 'soundId' of undefined"
}
And my repeating template is here:
<div layout horizontal wrap center center-justified>
<template repeat="{{s in carddata}}">
<sound-card image="{{s.imgurl}}"
quotetext="{{s.quote}}"
soundsrc="{{s.soundurl}}"
soundref="{{s.soundId}}"
downloadfunction="{{downloadFunction}}">
</sound-card>
</template>
</div>
Where carddata is just an array with my data in it. All of the values are generated fine so I know it's not an issue with my array. I'm just confused how exactly I'm supposed to target someting from within the repeating template? Am I calling it at the wrong time? Or am I messing up the syntax of the templateInstance bit?
If it matters, I'm trying to get it to work in an Android 4.4 webView using Apache Cordova. 4.4 webView doesn't appear to enjoy the shadowDOM terribly much.
Thanks!
edit: After some jiggery pokery with console logs, it appears that the sender value is referring to the div that I apply the on-click="{{downloadFunction}} to. Here's the template that I am repeating, if this provides any insight.
<div class="soundcard-container" vertical layout>
//can't target this one either on WebView 4.4, works on ChromeOS
<img src="{{image}}" on-tap="{{playAudio}}">
<div class="soundcard-bottom-container" horizontal layout center justified>
<span>{{quotetext}}</span>
//I have an 'a' tag for desktop browsers and the div tag is targeting my Android/iOS
//apps that I am exporting as a webView to using Apache Cordova. Webonly is hidden
//at the point where I'm trying to get my downloadfunction to work.
//console.log(sender) in my downloadfunction returns this div v
<div on-tap="{{downloadfunction}}" class="mobileonly"></div>
</div>
//just a hidden audio thing for web
<div style="display: none">
<audio id="{{soundref}}" src="{{soundsrc}}" controls preload="auto"></audio>
</div>
</div>
edit2 some console logs..
console.log(sender) and console.log(event.target) are both the same div that has the on-click event for my downloadFunction.. not sure if this should be the case.
console.log(e.target.templateInstance.model) returns my <sound-card> object, I believe like it should(?)
It's just when I add the specific .s.soundId that it's undefined. I'm not sure why it's unable to find it.. Maybe there's another way to get the specific soundId (or s.soundId rather) of that particular <sound-card> object?
I'll bet you want to refer to the "sender" of the event—not e.target. See the part about inSender at https://www.polymer-project.org/0.5/docs/polymer/polymer.html#declarative-event-mapping:
inSender: A reference to the node that declared the handler. This is
often different from inEvent.target (the lowest node that received the
event) and inEvent.currentTarget (the component processing the event),
so Polymer provides it directly.
This might fix it:
downloadFunction: function (e, detail, sender) {
console.log("dl function clicked");
//get particular id of thing
var fu = sender.templateInstance.model.s.soundId;
console.log(fu);
}
Alright I was able to fit this in a different way. I wasn't able to get e.target.templateInstance.model.s.soundId bit to work, so instead on the div that I call the event on (event.target) I gave it an attribute called data-soundid and passed it {{soundref}} from my original template and then where I repeat that template I simply made a function like so:
downloady: function (e) {
console.log(e.target.getAttribute('data-soundurl'));
}
Ta da! Very nice solution. Thanks to Eyal who suggested this to me in a previous question. It works like a charm. :-)
Here is working example of using templateInstance, with included selecting by dynamic ID: Plunk .
As for your code, can't tell why it's not working.
handleEvent: function(e, detail, sender) {
console.log('handleEvent');
console.log(sender.id);
//How to catch full_obj here,
//..as if first item is clicked: full_obj = {"firstName":"John", "lastName":"Doe"}
//console.log(e);
console.log(e.target.templateInstance.model.item.firstName);
//console.log(detail);
//console.log(sender);
this.instance_firstName = e.target.templateInstance.model.item.firstName;
this.instance_lastName = e.target.templateInstance.model.item.lastName;
//Selecting by dynamic ID
var clicked_element = this.shadowRoot.querySelector('#'+this.instance_firstName);
console.log('Selecting');
console.log(clicked_element);
//var second_element = sender.templateInstance.model.querySelector('my-second-element');
//var second_element = this.$.second_element;
}
Edit:
Event handling and data binding Docs
I'm creating an interface using JSF, and I'd like the value of one text field to provide the default for a second if the second hasn't yet been set. The crucial code will look something like this:
<h:outputScript>
function suggestValue2() {
var value2 = document.getElementById('value2').value;
if (value2 == "") {
document.getElementById('value2').value = document.getElementById('value1').value;
}
}
</h:outputScript>
<h:inputText
id="value1"
onblur="suggestValue2();" />
<h:inputText
id="value2" />
The problem is this doesn't actually work. The actual IDs of those two input elements get prefixed with some JSF-generated values, which tanks the getElementById calls. What's the best way for me to accomplish what I'm trying to accomplish here?
Edit: I should note that this is going to appear inside a composite component, which could wind up appearing multiple times on a single page. JSF dynamically setting the actual ID represents desired behavior.
Bind the component to the view,
<h:inputText binding="#{input1}" ... />
so that you can just print its client ID elsewhere in the view by UIComponent#getClientId().
<h:outputScript>
var input1 = document.getElementById('#{input1.clientId}');
// ...
</h:outputScript>
As you mentioned that you're inside a composite component, it may be good to know that composite component's own client ID is already available via #{cc.clientId}. So the more recommended alternative would be:
<cc:implementation>
<h:outputScript>
var input1 = document.getElementById('#{cc.clientId}:input1');
// ...
</h:outputScript>
...
<h:inputText id="input1" ... />
...
</cc:implementation>
See also:
Integrate JavaScript in JSF composite component, the clean way
Jsf uses a concept "naming containers" which says the id need not be unique within a provided container. Provided the container has an Id. So if you are not giving an Id to the container jsf appends the unpredictable values before the element. With id for container it becomes containerid:elements id. And this can be used in JavaScript reliably
I want to perform some logic in JavaScript when users click on the span element and update current XML instance from jQuery:
(I have seen 2 similar questions online but they never got answered!)
XForms:
<xhtml:span class="buttonPlusOne" id="plusVat">+</xhtml:span>
<xf:output ref="instance('submitted_instance')/TotVATAmnt"></xf:output>
<xf:input id="changeVatTotal" ref="instance('submitted_instance')/TotVATAmnt"></xf:input>
JavaScript:
$('span.buttonPlusOne').on('click', function () {
// do some logic and increment value for 0.01
orbeonElId = $(this).siblings('#changeVatTotal').children('input').attr('id');
// alert(orbeonElId) produces right id (changeVatTotal$xforms-input-1)
// alert(newValue) produces 0.02 (for example)
ORBEON.xforms.Document.setValue(orbeonElId, newValue);
});
I can see Orbeon posting data (Firebug), but the XML Instance does not get updated (input does not update the output - even though they share same "ref" attribute).
I suppose that you're mixing up the html element's id with the XForms id (id attribute) of the xf:input element.
The Orbeon documentation shows an example: the id to use in the ORBEON.xforms.Document.setValue() function call is the id of the (server-side) XForms element. So in your example it's changeVatTotal, and not the id of the (client-side) html input element changeVatTotal$xforms-input-1. This is why there's a request showing up in firebug with no effect on the XForms instance: the server-side XForms engine doesn't find a xf:input element with the id changeVatTotal$xforms-input-1, so it doesn't know what to do with that request.
This means, too, that you (usually) don't need to compute the id of the target element, instead you can just use the "plain" XForms id attribute value of the xf:input.
Alternatively:
Is it possible to handle the "plus" button completely in XForms? You could use a xforms:trigger control and include a xforms:setvalue action on the DOMActivate event:
<xf:trigger>
<xf:label>+</xf:label>
<xf:setvalue
ev:event="DOMActivate"
ref="instance('submitted_instance')/TotVATAmnt"
value="0.01 + instance('submitted_instance')/TotVATAmnt" />
<.... more actions ...>
</xf:trigger>
I think this solution would be more stable than doing some of the work client-side and some server-side.
I am adding elements dynamically using java script(Adding textboxes when we click add).Each of this textbox would be an element of a bList in my domain class.
See Below
Code:
Class A
{
Approach1
List<B> bList= LazyList.decorate(
new ArrayList<B>(), new InstantiateFactory(
B.class));
Approach2
List<B> bList= new AutoPopulatingList(B.class)
}
So basically i am trying to add elements to bList.
I know that i need to use autopopulatinglist or lazy list.But neither of these work.When i try to post the form it complains telling that collection has 0 elements and the index is invalid.
Is the above declaration enuf to ensure that i have the list ready to add elements.
Also when i read about using autopopulating list.Ref: http://blog.richardadamdean.com/?p=12
It says that we have to change the formBackingObject method in the controller to instantiate a new AutoPopulatingList:
Code:
ShoppingBasketForm sbf = new ShoppingBasketForm();
sbf.setItems(new AutoPopulatingList(ShoppingBasketItem.class));
But i am using spring webflow not spring MVC, So where exactly i put this logic.
Even if i try to access <form:input path="bList[0]" /> it would complain
Please advice.
https://jira.springsource.org/browse/SWF-990 <-- look at this issue.
I am trying out the following piece of code to get access a JSF component in Javascript by referring to its Id. But this fails.
JSF component:
<p:commandLink onclick="calculatePosition(this.id)" >
<h:graphicImage url="2.png"/>
</p:commandLink>
Javascript code:
<script type="text/javascript">
function calculatePosition(idOfClicked){
alert(idOfClicked);
var $element = jQuery('#'+idOfClicked);
var offset = $element.offset();
alert(offset.top);
}
</script>
1st alert works dislaying correct id of the element thereby proving that the JS function is called & correct id has been passed but it fails to display the 2nd alert. This happens only when the id of a JSF component is passed to this JavaScript function but works fine with non JSF components.
How can I make it work correctly ?
JSF prepends IDs of parent NamingContainer components (such as <h:form>) in generated client id with : as default separator character. So for example
<h:form id="foo">
<p:commandButton id="bar" />
...
will end up in generated HTML as
<form id="foo" name="foo">
<input type="submit" id="foo:bar" name="foo:bar" />
(rightclick page in webbrowser and choose View Source to see it yourself)
The : is however illegal in CSS identifiers. This was chosen so that the enduser won't accidently use it in component IDs which would only result in inaccessible parameters and components in the JSF side. To select an element with a : in the ID using CSS selectors in jQuery, you need to either escape it by backslash or to use the [id=...] attribute selector.
var $element1 = jQuery('#' + id.replace(':', '\\:'));
// or
var $element2 = jQuery('[id="' + id + '"]');
Alternatively, since JSF 2.0 you can override the ID separator character by a javax.faces.SEPARATOR_CHAR context parameter in web.xml with a different but CSS-valid value such as -. However, you need to be careful that you don't use this character yourself in any JSF component IDs.
As a completely different alternative, you can also just pass the whole HTML DOM element itself.
<p:commandButton onclick="calculatePosition(this)" />
so that you can do
function calculatePosition(element) {
var $element = jQuery(element);
// ...
}
without fiddling with IDs.