AngularJS - NgOptions from function returning undefined values - javascript

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!

Related

JS <select> listbox not working on click/change

what I need to do is to gather some data online via fetch and use the data to give the user infos and such (that I can do). In some cases, the fetch can return multiple results (an array of data), so I decided to create a element in the page to list all the names of the elements in the array (each element in the array is a sub-array with various infos, also a "name", which would be a location name).
I'm working on Chrome. All works, I store the data and this way I created another function to (theoretically) give the user the infos about the selected option in the listbox. If I call the function directly it works fine, meaning it returns all the infos it should. What actually doesn't work is the fact that this function returning infos should trigger on click/selecting any option from the list and it doesn't work. I don't get any error messages, it just does nothing.
What you see in this image is what happens when you click "filter" (it actually filters world locations detected with name similar to "Milano"), the user gets infos in the page and what you see in the right log side in the red square is returning the content of that array I mentioned (it contains data, so it's working), the index selected in the list (the last, so it's 5) and the coordinates of such selected location.
This happens just after the creation of the options because I directly call the function (returning data about the selected option), but if I use manually the list it just does nothing (as you see in the list, there's nothing logged after those coordinates).
I tried to create the options like this:
function createOption(text){
let listOption = new Option(text, text, true, true);
return listOption;
}
What I do directly to create the options in the list is a "for" loop for each element i in the array:
document.getElementById("keyword-results").append(createOption(data.data[i].station.name));
I also tried appendChild instead of append. As I said, this works, but the manual use of the list doesn't. What I declared is:
document.getElementById("keyword-results").addEventListener("onchange", selection());
being "selection()" the function returning the data.
function selection(){
let index = document.getElementById("keyword-results").selectedIndex;
console.log(index);
if (index > -1){
let currentResult = results.data[index];
let aqi = currentResult.aqi;
console.log(aqi);
document.getElementById("answer").innerHTML += `The estimated AQI [...]`;
let far = distance(currentResult.station.geo[0], currentResult.station.geo[1]);
if (far != null || far != undefined) {
document.getElementById("answer").innerHTML += `The estimated distance [...]`;
}
}
}
I also tried "change", "onclick" and "click" as methods to trigger the function but none of them works. Do you have any suggestions? I can't find anything useful here on stackoverflow nor on the web. If you want to check the whole code, this is my GitHub repository https://github.com/leorob88/pollution-forecast-API
document.getElementById("keyword-results").addEventListener("onchange", selection());
addEventListener expects a function as a second parameter, selection() is not a function but selection is.
When you use addEventListener, there is no such event named onchange its actually change
so it becomes:
document.getElementById("keyword-results").addEventListener("change", selection);
Reference.

Pentaho Javascript - row manipulation

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
}

jQuery .val(#) does not change selection following AJAX call - works if debugging/paused

I have an interesting issue - when I perform an AJAX call that refreshes this Appointment List dropdown with new entries based on either page load or a filter that is entered - the .val() method will not set
This is what success of the AJAX method will do - basically it sets back up the AppointmentList dropdown with new entries:
$.map(data, function (item) {
$('#AppointmentList').get(0).options[$('#AppointmentList').get(0).options.length] = new Option(item.AppointmentTime, item.ID);
});
This is what calls the function which basically just contains the $.ajax() method that re-populates the #AppointmentList dropdown. When I get the new set of values back - I still need it to have the old "appointment" pre-populated.
var tempVal = $('#AppointmentList').val();
DropDownList();
$('#AppointmentList').val(tempVal);
This does nothing, and the first element in the list re-created is selected.
However if I put a breakpoint on :
$('#AppointmentList').val(tempVal);
Then it seems enough time has passed for this dropdown to be able to be changed - if there is a breakpoint and I continue - the dropdown will change back to the value I want it to be if I am debugging the Javascript.
Any ideas on how to refactor this? I've been thinking maybe when we actually do the $.map() function we can set our old value up there - but this code seems to work... should I have a bit more time between when the Ajax finishes and I need to set the .val() again.
Ask a dumb question - figure out a dumb answer - I guess. Asynchronous. Duh.
Move those two lines to where this one is above the $.ajax() call:
var tempVal = $('#AppointmentList').val();
Then, put the line that sets the value within the success, but after the $.map():
$('#AppointmentList').val(tempVal);

dijit.byId('viewEditParameterValue').value does not return while .get('value') does

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.

Removing items from an ngList in Angular

I'm using ngList within an text box to get and post data to my server. The issue I've found is that while I can directly affect the generated array by removing indexes, when removing an item this way, the string in the input field is left unaffected.
The problem here is that as soon as the text field is modified, whatever is contained in that field immediately updates the model, restoring whatever items were removed.
http://plnkr.co/edit/EqkWwyLwvHrrhT6epOYP?p=preview
Does anyone have a solution for updating the string within the text field to match the model as the model is updated? My thought was to use an $apply either on my function or within a $watch but in both cases I got $apply in progress errors.
$scope.states.splice(index, 1);
It will not update ng-list because the change mechanism only invoked if previous value is not equal current value strictly...
So if you will create new instance instead of the splice current one nothing will be invoked because it is the same array instance so replace this code with the current one and it will be what you want...
var tmpList = angular.copy($scope.states);
tmpList.splice(index, 1);
$scope.states = tmpList;
and here is PLUNKER

Categories