I've read a similarly entitled article but it didn't really provide a client sided solution.
I have a radio button group that will determine whether or not other things will be visible or hidden. I have code that will retrieve the value of this RBGroup in a xp:scriptBlock.
function getPTValue (bName) {
var pt=null;
for(var i=0; i<document.forms[0].elements.length; i++){
if(document.forms[0].elements[i].name=="#{id:PayType}" ){
if(document.forms[0].elements[i].checked == true){
pt=document.forms[0].elements[i].value;
break; //remove this if for check box groups and collect multiple values above instead
}
}
}
return pt
}
Here is the radio button group;
<xp:radioGroup
id="PayType"
value="#{FInvoiceDoc.PayType}"
defaultValue="Hourly"
style="color:rgb(0,0,0)">
<xp:selectItem itemLabel="Hourly" itemValue="Hourly"> </xp:selectItem>
<xp:selectItem itemLabel="Fixed" itemValue="Fixed"></xp:selectItem>
<xp:eventHandler event="onclick" submit="true" refreshMode="norefresh">
<xp:this.script><![CDATA[payTypeVis();]]></xp:this.script>
</xp:eventHandler>
</xp:radioGroup>
This works great while the document is in edit mode, but if I open it in readonly mode, the above routine gets executed, but doesn't return the value of the radio button group.
It appears that in read-mode, it shows the the payType radio-button group as a quasi-computed field. No buttons, just the value. I try retrieving it with a XSP.getElementById("#{id:payType}").innerHTML and I get the value but with lots of HTML tags around it. (.value returns nothing)
How do I properly retrieve a radio button group value on a document in read mode using strictly CSJS?
The value of the field will not change in read mode, so for handling it in read mode, set a CSJS variable using the Script Block control and pulling directly from the bound field. Script Block controls allow you to run SSJS / Java as well, so:
var invDocPayType = "#{javascript:FInvoiceDoc.PayType}";
Set the rendered property so it only shows if the document is in read mode, so:
if (view.isRenderingPhase()) !FInvoiceDoc.isEditable();
Then in CSJS, check whether that variable exists (i.e. you're in read mode), otherwise get the value directly from the radio button dynamically.
I could think of a (possible) solution and a workaround.
The (possible) solution is to enable the "showReadonlyAsDisabled" property for your radio group. By (possible) i mean that i'm not 100% sure whether this exists for radio groups. But if it does your control should be rendered as a "control" with values in your html markup, with a "readOnly" attribute applied to it. Can't test this before tomorrow morning.
If this doesn't work you could also copy your value to a hidden field using the radio group's onchange event, then read that helper field's value which should be mich easier to retrieve.
Update:
just gave it a try: the "(possible)" solution unfortunately is not possible at all for radioGroups, so forget it.
You're most likely stuck with some other solution, as lined out in my 2nd option, or as #stwissel described it (his option #1). My workaround then would look a bit like this:
my radioGroup is bound to a field named rbGroup. There is also a simple data field on the same form named rbvalue, and on the Xpage I have an editBox control bound to rbvalue which is hidden through a css display:none statement. For this editBox I have the showReadonlyAsDisabled property set to true (for editBoxes this works):
<xp:inputText
id="rbGrpHelper"
value="#{doc1.rbValue}"
showReadonlyAsDisabled="true">
</xp:inputText>
The onchange event handler for my radioGroup performs some simple code copying the radio's selected value to rbvalue, and it performs a partial refresh on a div containing the rbGrpHelper editBox:
doc1.replaceItemValue("rbValue", doc.getItemValue("rbGroup"))
Now if my xpage is open in read mode, because of the showReadonlyAsDiabled property my hidden helper field looks like this in its HTML markup:
<input type="text"
value="1" id="view:_id1:rbGrpHelper"
name="view:_id1:rbGrpHelper"
readonly="readonly"
style="display:none"
class="xspInputFieldEditBox">
That way the rbGrpHelper is always up to date, and you can use your CSJS code to access the selected value.
Short: Don't
Long: By nature of forms, a readonly mode does not have input elements in it like radio buttons, inputboxes etc. You have a series of options:
You did bind your radio group to #{FInvoiceDoc.PayType}, so you could compute a hidden field (using a computed text with passthrou like <xp:text value="<:input type=\"hidden\" value=\"#{FInvoiceDoc.PayType}\"" escape="false"></xp:text>. Then simply use that value client side
If you need to switch even in read mode, you need to compute the radio group too, so it is switchable
Use a set of SSJS functions showSection_InterestingName(doc) {....} to compute the value true/false to show the sections in read mode (or use showSection(doc, sectionName). This way you abstract the computation from the display a little and it is easier to read for the dev after you
Hope that helps
Related
I'm implementing test cases for aviasales.com web sites and I'm trying to validate state of the checkbox.
I could easily find the checkbox and even click on it via:
WebElement checkboxValue = driver.findElement(
By.xpath("//label[#class='mewtwo-show_hotels__label']"));
checkboxValue.click();
The problem is that boolean bool = checkboxValue.isSelected(); returns only false even it was selected.
I googled a lot and found an advice to use JavaScript for that, so I tried from the console before Java implementation but same thing happens - always false:
var field = document.getElementsByClassName("mewtwo-show_hotels__label");
if (field[0].checked == true) {alert("1")} else {alert("2")}
and I got only alert with 2 no matter what is a checkbox condition (selected or not)
What else can I try here if chrome locator identifies checkbox as ::before in source code?
Thank you!
You should find the actual element for checkbox. What you have supposed to use is not correct, because it is label.
But there are elements on top of that:
Input with class - memtwo-hotels-checkbox and
Div with class - memtwo-custom_checkbox_wrapper
It is more likely there are some attributes which you can you to determine is element selected. If after that you cannot find any special attribute, then go to your DEV team and ask about providing the attribute.
You have custom checkbox, that is why any standard functions will not work. So come back to html code and try to find inside div some attribute which changes when you check and uncheck. When you find special attribute, then you need to do in java something like that:
if (element.getAttribute(MySpecialAttribute) != null) { //code here }
Hope it helps.
just query for checkbox, and not for the label
you need to select element with mewtwo-show_hotels__*checkbox* class (not mewtwo-show_hotels__*label*)
you see label, but it is just styled to reflect hidden checkbox state
Good evening,
I am writing an application using AngularJS and I require for the application to send data with a POST request to the nodejs server.
My data is structured like as a json object and it has data binding thanks to the AngularJS framework.
As of now, a function is dynamically trying to create possible values that the user might like inside of some input tags. An example:
<button ng-click="generateFoodAndBeverages(row)>Generate</button>
<input type="text" ng-model="row.service.day.beverage" placeholder="beverage" />
<input type="text" ng-model="row.service.day.food" placeholder="food" />
The two input values can be set by the user by typing in the value they would like (e.g. "Cola", "Hamburger"), but above the input tags is a button that can generate the input values for the user.
The function that generates the values takes them from an array and then at the end of the function returns two possible values, one for beverages and one for food.
When it has the two returning values it changes the attribute value of both inputs, setting them to the two possibilities generated by the function:
jQuery("#input1").attr("value", generateFoodAndBeverages(row)[0]);
jQuery("#input2").attr("value", generateFoodAndBeverages(row)[1]);
This is not perfect nor elegant but it's working. The function populates and dynamically changes the value attribute of those two input elements each time the user requests for automatic generation of food and beverages so the values are actually set and do exist.
Even so, even if I see them on screen as text inside the input fields, my POST request does not recognize the fact that the ng-model actually changed. The only way the ng-model registers the changes to the value attribute of the input fields is if the user types something with his keyboard, manually changing the value attribute. Another example:
<input type="text" value="generateValue()" ng-model="row.service.info" />
The one up here does not change the ng-model value at all.
<input type="text" value="User Typed Value" ng-model="row.service.info" />
This other one instead does change the ng-model value and as it changes and exists, it is passed to the $scope that can later be sent as a POST request to the server.
Any ideas as to why the "automatically and dynamically generated" value of the input field does not get registered by the ng-model while the user typed value does?
Thanks in advance!
[EDIT]
Apparently the problem comes with the ng-model not changing. I tried to debug the problem by applying an ng-change in the input. If the change is done by javascript, it is not registered with the ng-model and the ng-change function does not fire because the ng-model was not changed even tho' I can clearly see the new value set by javascript for the input tag. If I change the value of the input tag by hand the ng-change is fired and the console logs the change.
I could apply the changes directly to the ng-model if it weren't so different for each row.
Having the ng-model like this:
<input ng-model="row.serviceInfo.DayObject[dayString].food" />
<input ng-model="row.serviceInfo.DayObject[dayString].beverage" />
How would I be able to apply the changes directly to the ng-model given how dynamic the model is. As an example, I could have 1000 rows, each with their own serviceInfo object. I don't know how I could change the model for each of those rows with the dynamically generated values.
[EDIT]
The problem was indeed with ng-model not changing. The solution consisted in applying the changes to the ng-model for each element inside the dynamically generated values function. Thanks everyone for the input. I'll leave this piece of code here if anyone ever comes across the same problem! Thanks again!
let foodEl = angular.element(the row element food input);
let beverageEl = angular.element(the row element beverage input);
$scope.displayedCollection[i].serviceInfo = {
"day" : {
"food" : generatedValuesFood(el, day),
"beverage" : generatedValuesBeverage(el, day)
}
};
foodEl.val($scope.displayedCollection[i].serviceInfo.day.food);
beverageEl.val($scope.displayedCollection[i].serviceInfo.day.beverage);
I think that your problem is quite simple. As #ssougnez said, don't mixed jquery with angularjs. Angularjs use data-binding concept, don't use jquery style to change the input value instead use the ng-model directive to bind data from the model to the view on HTML controls (input, select, textarea). In your generateFoodAndBeverages function just set the ng-model value according to which row for eg:
var generateFoodAndBeverages = function () {
$scope.row.service.day.beverage = array[0];
$scope.row.service.day.food = array[1];
};
I am using some JQuery Combobox that you can check out here: https://simpletutorials.com/uploads/1860/demo/index.html
As you can see, you can start typing and get the results filtered.
However, once you have selected a value, when clicking on the arrow to open the list, no other values are shown anymore. So, if I want to change college/state, I need to manually clear the input value. I don't like this, so I want to modify it.
I changed that code and added this JS on the click event of the list:
onclick="document.getElementById('statesCombo-ddi').value='';"
This line basically finds the input by id and sets its value to an empty string.
You can try out by looking for the td element having class "stc-button" (with Chrome, just focus on the arrow of the second combo box) and add my code to the tag.
===EDIT===
You can obtain the same results by adding this code directly to the input:
onclick="this.value=''"
===END EDIT===
This has a weird behavior:
If I SELECT an element from the list, it clears the value and everything works correctly.
If I TYPE some letters and then select a value from the list, no item is shown in the list after clicking.
What's wrong with it?
You can override one of the combo box methods to accomplish this:
STComboBox.prototype.filterAndResetSelected = function() {
this.$('ddi').val('');
this.filterList('');
this.selectRow(0);
this.$('ddl').scrollTop(0);
};
Does this help?
The unminified code is provided, is relatively small (12kb) and is fairly well commented, so you could make this modification directly to the source if you'd like.
Edit: Fixed to clear the input value (as indicated in the comment below)
By reading the source and doing a little debugging with Chrome's inspector (Control+Shift+i), you can find the particular ID of the element you need to clear (#collegesCombo-ddi) in order to clear the input box. Once you've found the element's ID you need to clear (and being very careful with plugins that assign multiple elements with the same ID, which is not allowed in the standard, and an indicator of poorly-written code):
$('#collegesCombo-ddi').val('');
I have an issue perhaps very similar to
How do I make a required radio input optional in Firefox using JavaScript?
My example can be found here:
http://www.bradkent.com/?page=test/ff_radio
In a nutshell, I have an event viewer on a checkbox that toggles the visibility of a radio group. The radio group is initially required, but when hidden, I change the radio inputs' required property to false (node.required = false). When the group is re-shown, the required property is changed back to true.
the dom inspector confirms that neither the required attribute or property is set.
So why is it requiring an option to be selected?
What am I doing wrong, or overlooking?
Thank you
well, I figured out the issue
node.required = true/false vs node.setAttribute('required',1); and node.removeAttribute('required');
the former had been done earlier in the code and at that point node.removeAttribute('required'); node.removeProp('required'); etc were all of no use in removing the required property (in Firefox)
I need to hide a text input field with javascript. Changing its type attribute to hidden does not work in IE (security issue).
What would be the best way to do it?
Note: No jQuery or other lib can be assumed.
I assume you have to show and hide the text field dynamically based on changing conditions in the form, otherwise you'd just make it an <input type="hidden"... to begin with.
Keep your code that shows and hides the field as it is, but also catch the onsubmit event.
In the submit handler, get your text field via document.getElementById(...) (or by accessing document.forms[i]) and check to see whether or not it's hidden.
If it is hidden, create a new DOM node for an <input type="hidden" ...> field and add that node to the form, probably via myform.appendChild(...). You'll have to give it the name your server-side code expects. Copy the contents of the hidden text field into the newly created type=hidden field, then return from your submit handler, allowing the standard submit to continue.
You could also just un-hide the text field on submit, but you'd have to move it "off screen" also or the user would see it reappear during submit processing.
Try wrapping it in a div or span and then setting the display style to none when you want to hide it, and then to block (if you used a div) or inline (if you used a span) when you want to show it.
document.myform.myelement.style.display = 'none'
works as expected even in Internet Explorer.
The only way you can change it is before you append it to the DOM. You can make a new element and then replace the current one with it.
Look at replaceChild and createElement since you want to do manual DOM scripting. I assume you know what to do.
EDIT: "Hidden" fields as far as I know are sent. Have you checked whether they are? And you can also just do position:absolute; left:-9999em; to offset them.