I am trying to manipulate a row using javascript in an older version of pentaho 4.4) and getting some strange results that I can't explain / don't understand what Pentaho is doing
var test = 'field';
Alert (this[test]); //--> Undefined
Alert (this['field']); // --> Expected result
Alert (this[test]); //--> Expected Result
For some reason, the initial request for this[test] is undefined until I use the literal string reference making it impossible to dynamically drive the process (i.e. I can't access row information by references).
Any ideas as to why? Is it simply how Pentaho deals with variables? Effectively I want my end result to allow me to change the row value at any given position. Either:
row[test] = 'New value
or
this[test] = 'New Value
or
this[test].setValue('New Value');
However, none of the above work, without replacing the values making it a very static process.
As far as I can see, Kettle does not add a field to the script's scope, unless the field is contained as a substring in the script source code (it should add even if the field mentioned in the comment). See determineUsedFields() and addValues() methods (https://github.com/pentaho/pentaho-kettle/blob/4.4.0/src/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesMod.java#L106).
So, the exact script you've provided, actually, produces either three defined values, or three undefined values, depending on whether the field exists or not. I was able to reproduce your issue only after I've removed strings with the field name from the code completely, and passed the field name in another field.
So, one way to manipulate row values could be to mention all field names in the script (e.g. in a comment), then try to use setValue as you have tried (seems to work in compatibility mode only).
Another possible way is to use the row array variable to get values and getInputRowMeta().indexOfValue(fieldName) to get the index of the field, e.g:
var idx = getInputRowMeta().indexOfValue(fieldName)
// WARNING: you may assign value of any type this way
// and the value will not be converted to a type defined
// in the field's ValueMeta:
row[idx] = 'New value'
However, this approach bypasses type conversions, which are usually performed while passing JavaScript values outside of the JS step in getValueFromJScript() method.
For example, the following code will put invalid value in the output, and you may not even notice it until some subsequent step will handle the value in some improper way:
// Let's assume that fieldName is name of the 0th input field.
// I'd expect, that the value would remain the same
// but in fact the `fieldName` references some wrapper oject
// which looks similar to its value
// but has a different type
row[0] = fieldName;
In subsequent JS step:
for(var i = 0; i < row.length; i++) {
Alert(row[i]) // alerts same value as the input, e.g. 'test'
Alert(row[i].class) // alerts undefined. While expected is 'java.lang.String'
// Some other subsequent steps may crash once this value encountered
}
Related
I am trying to prevent duplicate items from being entered in an Interactive Grid in Oracle Apex 20.2. I do get a unique constraint error when this happens, but this is for a barcode scanning stock control app and the unique constraint error only happens when saving after scanning a room with lots of objects. It is then very difficult to find the duplicate field. You also cannot use sort, since that wants to refresh the page and looses all your scanned items. I cannot presort because I want the last scanned item on top.
I was able to add Javascript on page load that creates an array with all the barcodes. I then check this array when scanning and do not add new Interactive Grid rows when a duplicate barcode is going to be added to the array.
In addition to this I need to add the same for when an Interactive Grid row is manually entered. For this I wanted to add a Javascript dynamic action on the barcode column in the Interactive Grid, in order to once again check the global array for uniqueness. However I have several issues: I cannot figure out how the get the entered barcode value in the change dynamic action Javascript, sometimes it shows the previous changed value (might be this bug although I am in 20.2) and the Change event also seems to fire twice when hitting enter after entering a value (once for the new row (this time my code works unlike when hitting Tab) and once for the next row below). The last one seems bad, since then it will try to check existing values (the next row) and give errors that should not happen; however I do not see a more appropriate event like On Row Submit. Not sure if there is a way to check whether the value changed on the Change event.
The code I currently have I got from here. I am assuming this means Oracle Apex does not have a standard way of getting an Interactive Grid column value in a Javascript dynamic action. Not sure if this has changed in 20.2 or 21. The code I have is:
console.log($(this.triggeringElement));
var grid = apex.region('LINES').widget().interactiveGrid('getViews', 'grid');
var model = grid.model;
var selectedRow = grid.view$.grid('getSelection');
var id = $(selectedRow[0][0]).data('id');
var record = model.getRecord(id);
let bcode = model.getValue(record, 'BARCODE');
console.log(id);
console.log(record);
console.log($(selectedRow[0][0]));
console.log(bcode);
if(barcodes.includes(bcode)) {
apex.message.showErrors([{
type: "error",
location: "page",
message: "The entered barcode is already in the list.",
unsafe: false
}]);
}
When I console.log(record) I can see values that I enter into the barcode column, but I do not know how to walk the object tree in order to retrieve the value out of the record. I do not understand the object it shows me in the console log. It does not seem to correlate with the dot access traversals that others are doing in the above code. I can see the record array at the top, but for that the barcode column shows the previous value; below that it does however show the newly entered value as the third (2) index, but I do not know how to write Javascript to access that.
If I can access the previous and new value from the record object I could check for changes and also compare the new value against the global array. How do I access these values in the record object or is there a better way of achieving my goal? bcode prints the previous value, so I guess I already have that if that is not a bug.
I have a table in a form with a list of products where there is an input for each (let's call it 'pc'). Each input is named as 'pc' and product id with an id as the same. IE: 'pc100', 'pc101', etc. Each input has an onkeyup event to call a function to populate a price where I pass the product id (onkeyup='myfunction(100) The function receives the id but I cannot configure the javascript to that id. I will have the rest of the code as long as I can get the dynamic variable name. The internet is full of all kinds of things like eval() and window[] and I have tried every possible combination I can think of/find. I know it's possible to get this to work. So...how can I get this alert to work?
Most the results I will give me 'pc100' when I need 'Heres my test'
function myfunction(idpro) {
var pc331 = 'Heres my test';
alert( "pc" + idpro );
}
Don't use dynamic variable names. Do use look-ups in data structures:
function f(id) {
var pc = {
331: "Here's my test"
}
console.log(pc[id]);
}
Dynamic variables are a huge problem, especially from a security perspective. If you were naive and used eval someone could construct an id value that executes arbitrary JavaScript and then you have an XSS problem.
I have a large set of embedded data fields that are called rnd1, rnd2, rnd3 etc. In a certain question block, I stored to each of these a certain value (each a different random number).
I also have a Loop and Merge question block, and in each round, I would like to access the stored data of a different field (i.e. in the 1st round I'd like to access whatever is in rnd1, in the 2nd round access rnd2 etc.) Can this be done in Qualtrics?
I tried something like:
Qualtrics.SurveyEngine.addOnload(function()
{
var trialNum = this.questionId.split('_')[0]; // getting the loop's current round number
var EDname = "rnd"+trialNum; // name of desired EF field
var rndNum = "${e://Field/" + EDname + "}"; // this is where I'd like stored the right ED value
// some more code that uses rndNum
});
but this does not work. It seems that while EDname gets the right string, I cannot access the value of that embedded field this way (though var rndNum = "${e://Field/rnd1} does work and returns the right value, so the problem seems to be in the looping strucutre).
If I cannot loop over the different fields in the JS code for some reason, is there another clever way to get that done in Qualtrics? For example, I thought it may be possible to use the different field names in the Loop and Merge section as "Field 2", but this seem to require me setting manually each and every ED field name.
Thanks.
Piped embedded data fields are resolved on the server before the page gets sent to your browser. So, it is impossible to dynamically create an embedded data field name and resolve it on the client side with JavaScript.
The way you are doing it with a loop & merge field is the best way.
I've got an application which has to show some options inside a select depending on a previous option. To achieve this, I've put the logic to show those options inside a controller function, like this:
vm.getScopeValues = function(tp){
var vals = [];
vals.push({n: 'Opt1', v: 'opt1'});
if(!tp || tp != 'somevalue'){
vals.push({n: 'Opt2', v: 'opt2'});
}
return vals;
};
The problem is that sometimes, I get an undefined as the value of the select options. On the following jsFiddle you can see a simpler approach, but with same result:
https://jsfiddle.net/nr9ffrkk/
As you can see:
If I write track by v, I get undefined
If I write track by o.v, then the values are right, but the ng-model does not get matched correctly
If I write o.v as o.n... without the track by, I get an error ($digest cycles)
When everything gets matched correctly (I achieved it somehow but cannot remember how), if I add a new dynamic "field" (click on "ADD NEW FIELD"), then they come out as undefined values again
I've made console.log to watch the returning values of the function, and it gets called correctly and returns the right values (nothing undefined).
I need to be able to create dinamycally new entries on the fields array (with an initial value for type, of course) and that the select gets the right values for the options.
UPDATED
As you can see, making a controller variable (not a function) with the values does not work neither, bringing the same problem:
https://jsfiddle.net/dgy5ryvh/
Thank you!
I have defined two Text input in my html like this..
<revit:validationTextBox id="viewEditParameterValue" maxLength="2500"
required="true"
invalidMessage="#{commonuielements.msg_invalid_input}">
</revit:validationTextBox>
<revit:validationTextBox id="viewEditParameterValDefault"
maxLength="100"
regExp="#{commonuielements.parameter_default_value_regex}"
invalidMessage="#{commonuielements.msg_invalid_input}"
trim="true"></revit:validationTextBox>
I am trying to get the value of two TextBox in a java script function like this..
var value = dijit.byId('viewEditParameterValDefault').value;
var parValue = dijit.byId('viewEditParameterValue').value;
But for the first one I get the value but second line returns blank whereas If I use below line I get the value.
var parValue = dijit.byId('viewEditParameterValue').get('value');
Does anybody have any guess what could be the reason?
get('value') is the correct way to retrieve the value of a Dijit form input widget. Accessing value directly isn't guaranteed to give you consistent results (or the results you expect), since it will be implementation-dependent. This is perhaps even more important for certain subclasses of TextBox where formatting or mapping come into play.
Moreover, setting value directly won't accomplish anything, whereas calling set('value', ...) will properly update the widget.