priority-web-sdk: Implementing a choose-field - javascript

I'm trying to implement a choose-field with a <select> control.
<div id="container" onchange="fieldChangeHandler(event)">
...
<div class="item" >
<label>Status</label>
<select id="STATDES" onfocus="focusdiv(event)" onblur="defocusdiv(event)"></select>
</div>
In the updateFields() handler I identify the control type:
function updateFields(result) {
if (result[myForm.name]) {
var fields = result[myForm.name][1];
for (var fieldName in fields) {
var el = document.getElementById(fieldName);
if (el) {
switch (el.nodeName){
case "INPUT":
el.value = fields[fieldName];
break;
case 'SELECT':
fill(el, fields[fieldName]);
el.value = fields[fieldName];
break;
};
};
}
}
}
...And if the control is a <select> I fill in the options with a call to the form choose:
function fill(el, sel){
myForm.choose(el.id, "").then(
function (searchObj) {
var i, ch;
$('#'+el.id).empty();
for (i in searchObj.ChooseLine) {
ch = searchObj.ChooseLine[i];
if (ch.string1 == sel){
$("#"+el.id).append('<option selected value="'+ ch.string1 +'">'+ ch.string1 +'</option>');
} else {
$('#'+el.id).append('<option value="'+ ch.string1 +'">'+ ch.string1 +'</option>');
};
};
},
function (serverResponse) {
alert(serverResponse.message);
}
);
};
Subsequent calls to the fieldChangeHandler by the <select> onchange event call the fieldUpdate method on the loaded form:
function fieldChangeHandler(event) {
console.log("%s=%s", event.srcElement.id, event.target.value);
myForm.fieldUpdate(event.srcElement.id, event.target.value);
}
This all works fine till I try to save the current form record.
function saveHandler() {
myForm.saveRow(
0,
function(){
console.log("Row Saved.");
},
function(serverResponse){
console.log("%j", serverResponse);
});
}
where I get the following output:
Object {type: "error", ...}
code:"stop"
fatal:false
form:Object
message:"Status missing."
type:"error"
__proto__:Object
How do I override the saveRow function to make it retrieve it's data from the <select> control please?

You MUST specify the current value in choose parameters. It won't read it from the current record as I (mis)read the docs..
Note: If the field currently cotains a value, it will automatically be
filled in as fieldValue, even if a different fieldValue was specified.
So, the fill function should look like this...
function fill(el, sel){
myForm.choose(el.id, sel).then(
...
};

I just want to point something out. The choose method : myform.choose is not necessarily called after a field update.
I understand that in ur case the choose list gets different values for each field update and that u need to update ur select. Which is cool but in case someone uses a choose list that is not changed after fields updates it is better to call this method only once!
Just writing it here to clarify things about the choose method :)

Related

Dynamically check javascript value after database update

I am developing a dynamically generated and self updating form in ASP.NET MVC using javavascript, Jquery, JSON/Ajax calls.
Here is how I set up my view code from the controller. I loop through all available controls from the controller:
<ul>
#using (Html.BeginForm("Index", "WebMan", FormMethod.Post)) {
foreach (var row in Model.controls)
{
<li>
<label>#row.Name</label>
#if (row.ControlType == "STRING" || row.ControlType == COMMENT")
{
<input type="text" name="#row.Name" id="#row.NameID" value="#row.Value" data-original-value="#row.Value" class="form-control data-field" style="width: 300px"/>
}
else if (row.ControlType == "DDL")
{
<select name="#row.Name" id="#row.NameID" class="form-control data-field" value="#row.Value" data-original-value="#row.Value" style="width: 300px">
#foreach (var o in row.Options)
{
<option value="#o.Value">#o.Text</option>
}
</select>
}
</li>
}
<button type="submit">Update</button>
}
</ul>
(notice that I set the value to the value from the database and I also set the “data-original-value” to the value from the database as well)
I am using the “data-original-value” to check to see if the value has changed later.
I also set up a javascript timer that executes every 5 seconds. This timer is meant to “update” the page. (code for timer below)
var interval = setInterval(function () { Update(); }, 10000);
When the timer executes, we loop through each control in the “data-field” class. This allows me to check each dynamically generated control.
Basically, If a user has edited a control, I DO NOT want to update that control, I want to ignore it. I only want to update that specific control if a user has not changed the value. When a user changes the value, the current value != orig value (Data-original-value), so we set the field to yellow and ignore the database update code.
function Update() {
UpdateControls();
}
function UpdateControls() {
$(".data-field").each(function () {
var nameAttr = $(this).attr('name');
var id = $(this).attr('id');
var val = document.getElementById(id).value;
var origVal = $(this).data("original-value");
if (origVal == val) {
//user did not change control, update from database
var url = "/WebMan/UpdateControlsFromDB/";
$.ajax({
url: url,
data: { name: nameAttr },
cache: false,
type: "POST",
success: function (data) {
if (data != null) {
document.getElementById(id).setAttribute("data-original-value", data);
document.getElementById(id).value = data;
}
else {
alert(data);
}
},
error: function (response) {
alert("Issue updating the page controls from database");
}
});
}
else {
document.getElementById(id).style.backgroundColor = "yellow";
//user changed control, do not update control and change color
}
});
}
If no change, this ajax method in my controller is called:
[HttpPost]
public ActionResult UpdateControlsFromDB(string name)
{
var curValue= db.Setup.Where(x => x.Name == name).Select(x =>Value).FirstOrDefault();
return Json(curValue);
}
The code works correctly if a user modifies the field. It senses that the user modifies the code, and changes the field yellow.
The part that does not work correctly, is if the database updates the field. When the database first updates the field, it looks great. We set the “data-original-field” value to the value as well, to tell our code that is should not turn yellow and the user has not modified it.
But after another update, “value” and “original-value” do not match. The code document.getElementById(id).value somehow gets the OLD version of the control. It does not get the current value. So then on next loop, the values don’t match and we stop updating from DB and the control turns yellow.
My issue is that my code senses that the control value changed (database update) and turns it yellow, when I only want to turn the control yellow when a USER has changed the value in the control.
I only want to change the control and prevent updating from DB when the control has been modified by the user.
Thank you for any help.

jquery get data attributes from dynamically generated options

I am creating a drop down dynamically after an ajax all and populating the fields. I am also calling jquery.data() to set some attribute which I want in future.
HTML
<input id="test" type="text" list="mylist"/>
<datalist id="mylist"></datalist>
JS
$(function() {
// assume this data is coming from ajax call
var data = [{
"name": "John",
"id": 1
}, {
"name": "Jane",
"id": 2
}, {
"name": "Judie",
"id": 3
}];
var generateDropDown = function(data) {
var datalist = $('#mylist');
for (var i = 0; i < data.length; i++) {
var value = data[i].name + ' => ' + data[i].id;
$('<option>', {
'class': 'myclass'
})
.val(value)
.data('extra', {
'newid': data[i] * 100
})
.appendTo(datalist);
}
};
generateDropDown(data);
$('.myclass').on('select', function(selected) {
console.log($(selected).data('extra'));
console.log($(this).data('extra'));
});
});
Here is the JSFiddle
My requirement is to access the selected value from drop down along with the data attribute i have added. How can I do that ?
I tried the 2 console.log options as mentioned above but they dont print anything.
In comparison to HTMLSelectElement object, HTMLDataListElement object doesn't have selectedIndex property, so it seems you have to filter the options for getting the possible selected option.
$('#test').on('change', function (/* event */) {
var val = this.value;
var data = $(this.list.options).filter(function() {
return this.value === val;
}).data('extra');
});
Here is a demo.
Also note that data[i] * 100 results in a NaN (Not a Number) value as you are multiplying an object by a number and it doesn't make any sense!
When using a datalist, think of it as just a list of suggestions for the user. The user can type whatever he/she wants. The option elements are not related to the actual selected value which is stored in the textbox. If you must use a datalist, then use an event on the textbox and select the option based on the value. Something like:
$('#test').on('change', function(selected) {
alert($("#mylist option[value='"+$(this).val()+"']").data('extra'));
});
This takes the textbox value and finds the associated datalist option. However, if I type some random gibberish, it won't and can't work since no corresponding option exists. The alternative is to use a select which forces the user to choose one of the options in the list.
If you want a select, take a look at https://jsfiddle.net/tscxyw5m/
Essentially now we can do:
$("#mylist").on('change', function() {
alert($(this).find("option:selected").data("extra"));
});
Because now the options are actually associated with the select.
Also note I think you meant:
'newid': data[i].id * 100
Not
'newid': data[i] * 100
Which yields NaN.
DEMO: https://jsfiddle.net/erkaner/9yb6km6a/21/
When you try to get the value of the selected item, you need to search through the options in the page and bring the option item that matches with the value in the input field:
$("#test").bind('input', function () {
alert($('body')
.find(
'option[value*="' + $(this).val() + '"]'
).data('extra').newid);
});

updating a json value with angular

I am trying to update an json object value from a textbox using angular and I'm not sure what the best way to go about it is.
This is the json object...
$scope.productAttributes = {
"CostRequirements":[
{
"OriginPostcode": 'NW1BT',
"BearerSize":100
}
]
}
And when a use types in a text field and clicks a button, I would like to grab that textfield value and pass it into the json object to replace the postcose value (OriginPostcode) I tried to pass in a scope variable but that didnt work.
<input type="text" placeholder="Please enter postcode" class="form-control" ng-model="sitePostcode"/>
And this is the fucntion that is fired when the user clicks a button to submit the json
var loadPrices = function () {
productsServices.getPrices1($scope.productAttributes)
.then(function (res) {
$scope.selectedProductPrices = res.data.Products;
// $scope.selectedProductAddOns = res.data.product_addons;
})
.finally(function () {
$scope.loadingPrices = false;
$scope.loadedPrices = true;
});
};
Could anyone tell me what I need to do to put the user input in the textbox into the json object?
Many thanks
What we don't see is the function that runs the update with the button. It should look something like this
// your HTML button
<button ng-click='updateThingy()'>Update</button>
// your HTML input
<input type="text" ng-model="myObject.sitePostcode"/>
// your controller
$scope.myObject = { // ties to the ng-model, you want to tie to a property of an object rather than just a scope property
sitePostcode : $scope.productAttributes.CostRequirements[0].OriginPostcode // load in post code from productAttributes
};
$scope.updateThingy = function(){
$scope.productAttributes.CostRequirements[0].OriginPostcode = $scope.myObject.sitePostcode;
};
Here is a demo plunker for updating a value on button click, hope it helps out.
http://plnkr.co/edit/8PsVgWbr2hMvgx8xEMR1?p=preview
I guess loadPrices function is inside your controller. Well, then you should have sitePostCode variable available inside your controller and your function. So you just need to inject that value inside $scope.productAttributes.
$scope.productAttributes.sitePostCode = $scope.sitePostCode;
This you need to put it before you make the productsServices.getPrices1 call.
var loadPrices = function() {
$scope.productAttributes.sitePostCode = $scope.sitePostCode;
productsServices.getPrices1($scope.productAttributes)
.then(function(res) {
$scope.selectedProductPrices = res.data.Products;
// $scope.selectedProductAddOns = res.data.product_addons;
})
.finally(function() {
$scope.loadingPrices = false;
$scope.loadedPrices = true;
});
};
Let me know if it worked.

Retrieve the disabled attributes even after page refresh using localStorage

I have an HTML code with a select tag where the options are dynamically populated. Once the onchange event occurs the option selected gets disabled. And also if any page navigation happens the options populated previously are retrieved.
In my case once options are populated and any option is selected gets disabled( intention to not allow the user to select it again). So there might be a case where out of 3 options only two are selected and disabled so once I refresh and the options not selected previously should be enabled. And the options selected previously should be disabled. But my code enables all the options after refresh. How can I fix this?
html code
<select id="convoy_list" id="list" onchange="fnSelected(this)">
<option>Values</option>
</select>
js code
//This function says what happnes on option change
function fnSelected(selctdOption){
var vehId=selctdOption.options[selctdOption.selectedIndex].disabled=true;
localStorage.setItem("vehId",vehId);
//some code and further process
}
//this function says the process on the drop-down list --on how data is populated
function test(){
$.ajax({
//some requests and data sent
//get the response back
success:function(responsedata){
for(i=0;i<responsedata.data;i++):
{
var unitID=//some value from the ajax response
if(somecondition)
{
var select=$(#convoy_list);
$('<option>').text(unitID).appendTo(select);
var conArr=[];
conArr=unitID;
test=JSON.stringify(conArr);
localStorage.setItem("test"+i,test);
}
}
}
});
}
//In the display function--on refresh how the stored are retrievd.
function display(){
for(var i=0;i<localStorage.length;i++){
var listId=$.parseJSON(localStorage.getItem("test"+i)));
var select=$(#list);
$('<option>').text(listId).appendTo(select);
}
}
In the display function the previously populated values for the drop down are retrieved but the options which were selected are not disabled. Instead all the options are enabled.
I tried the following in display function
if(localStorage.getItem("vehId")==true){
var select=$(#list);
$('<option>').text(listId).attr("disabled",true).appendTo(select);
}
But this does not work.
Elements on your page shouldn't have same ids
<select id="convoy_list" onchange="fnSelected(this)">
<option>Values</option>
</select>
In your fnSelected() function you always store item {"vehId" : true} no matter what item is selected. Instead, you should for example first assign some Id to each <option\> and then save the state only for them.
For example:
function test(){
$.ajax({
//some requests and data sent
//get the response back
success:function(responsedata){
for(i=0;i<responsedata.data;i++):
{
var unitID=//some value from the ajax response
if(somecondition)
{
var select=$("#convoy_list"); \\don't forget quotes with selectors.
var itemId = "test" + i;
$('<option>').text(unitID).attr("id", itemId) \\we have set id for option
.appendTo(select);
var conArr=[];
conArr=unitID;
test=JSON.stringify(conArr);
localStorage.setItem(itemId,test);
}
}
}
});
}
Now we can use that id in fnSelected():
function fnSelected(options) {
var selected = $(options).children(":selected");
selected.prop("disabled","disabled");
localStorage.setItem(selected.attr("id") + "disabled", true);
}
And now in display():
function display(){
for(var i=0;i<localStorage.length;i++){
var listId = $.parseJSON(localStorage.getItem("test"+i)));
var select = $("convoy_list");
var option = $('<option>').text(listId).id(listId);
.appendTo(select);
if(localStorage.getItem(listId + "disabled") == "true"){
option.prop("disabled","disabled");
}
option.appendTo(select);
}
}
Also maybe not intended you used following shortcut in your fnSelected:
var a = b = val;
which is the same as b = val; var a = b;
So your fnSelected() function was equivalent to
function fnSelected(selctdOption){
selctdOption.options[selctdOption.selectedIndex].disabled=true;
var vehId = selctdOption.options[selctdOption.selectedIndex].disabled;
localStorage.setItem("vehId",vehId); \\ and "vehId" is just a string, always the same.
}
Beware of some errors, I didn't test all of this, but hope logic is understood.

How to populate a dropdown list based on values of the another list?

I want to implement a search box same as this, at first, just first dropdown list is active once user selects an option from the first dropbox, the second dropdown box will be activated and its list will be populated.
<s:select id="country" name="country" label="Country" list="%{country} onchange="findCities(this.value)"/>
<s:select id="city" name="city" label="Location" list=""/>
Jquery chained plugin will serve your purpose,
https://plugins.jquery.com/chained/
usage link - http://www.appelsiini.net/projects/chained
this plugin will chain your textboxes.
Try this code where based on your needs you have to populate it with your options:
var x;
$('#pu-country').on('change', function () {
if (this.value != '0') {
$('#pu-city').prop('disabled', false);
$('#pu-city').find("option").not(":first").remove();
$('#pu-location').prop('disabled', true);
$('#pu-location').val("Choose");
switch (this.value) {
case 'A':
x = '<option value="A.1">A.1</option><option value="A.2">A.2</option><option value="A.3">A.3</option>'
}
$('#pu-city').append(x)
} else {
$('#pu-location').prop('disabled', true);
$('#pu-location').val("Choose");
$('#pu-city').prop('disabled', true);
$('#pu-city').val("Choose");
}
});
$('#pu-city').on('change', function () {
if (this.value != '0') {
$('#pu-location').prop('disabled', false);
$('#pu-location').find("option").not(":first").remove();
switch (this.value) {
case 'A.1':
x = '<option value="A.1.1">A.1.1</option><option value="A.1.2">A.1.2</option><option value="A.1.3">A.1.3</option>'
break;
case 'A.2':
x = '<option value="A.2.1">A.2.1</option><option value="A.2.2">A.2.2</option><option value="A.2.3">A.2.3</option>'
break;
case 'A.3':
x = '<option value="A.3.1">A.3.1</option><option value="A.3.2">A.3.2</option><option value="A.3.3">A.3.3</option>'
break;
}
$('#pu-location').append(x)
} else {
$('#pu-location').prop('disabled', true);
$('#pu-location').val("Choose");
}
});
I have also set up and a demo to see the functionallity with more options.
FIDDLE
Your code should be something like this:
$(country).change(function(){
var l=Document.getElementByID("country");
for(i=0;i<=l.length;i++)
{
if(l.options[i].selected?)
{
text_array=[HERE YOU NEED TO ADD THE CITIES OF l.options[i].text];
val_array=[HERE YOU NEED TO ADD THE VALUES OF THECITIES OF l.options[i].text];
}
}
var c=Document.getElementByID("city");
c.options.text=[];
c.options.value=[];
//You now should have an empty select.
c.options.text=text_array ;
c.options.value=val_array ;
});
As I don't know, what kind of DB you use, to have the cities connected to their countrys, I can't tell you, what to put into the uppercase text...
Ciao j888, in this fiddle i tried to reconstruct the same system as the site you provided the link
the number of states cityes and locality is less but the concept remains the same
If you want to add a new state you must enter a new html options in select#paese with an id.
Then you have add in obj.citta a property with this id name and an array of cityes for a value.
The same thing for obj.localita where you will create an array of arrays.
The jQuery code you need is
<script type="text/javascript">
$(document).ready(function(){
var obj={
citta:{ //value is the same of option id
albania:['Durres','Tirana'],
austria:['Vienna','innsbruck','Graz'],
},
localita:{//for every city create a sub array of places
albania:[['località Durres1','località Durres 2'],['località Tirana','località Tirana 2']],
austria:[['località Vienna','località Vienna 2'],['località innsbruck','località innsbruck 2'],['località Graz','località Graz 2','località Graz 3']],
}
}
$('#paese').on('change',function(){
$('#località').attr('disabled','disabled').find('option').remove()
var quale=$(this).find('option:selected').attr('id')
var arr=obj.citta[quale]
if(arr){
$('#citta').removeAttr('disabled')
$('#citta option.added').remove()
for(i=0;i<arr.length;i++){
$('<option class="added">'+arr[i]+'</option>').appendTo('#citta')
}
}
})
$('#citta').on('change',function(){
var ind=($(this).find('option:selected').index())-1
var quale=$('#paese').find('option:selected').attr('id')
var arr=obj.localita[quale][ind]
if(arr){
$('#località').removeAttr('disabled')
$('#località option.added').remove()
for(i=0;i<arr.length;i++){
$('<option class="added">'+arr[i]+'</option>').appendTo('#località')
}
}
})
})
</script>
If this solution does not suit your needs, i apologize for making you lose time.
Hi i have done this for license and its dependent subject in yii 1.
The license dropdown
//php code
foreach($subject as $v) {
$subj .= $v['licenseId'] . ":" . $v['subjectId'] . ":" . $v['displayName'] . ";";
}
Yii::app()->clientScript->registerScript('variables', 'var subj = "' . $subj . '";', CClientScript::POS_HEAD);
?>
//javascript code
jQuery(document).ready(function($) {
//subject. dependent dropdown list based on licnse
var ty, subjs = subj.split(';'), subjSel = []; //subj register this varible from php it is
for(var i=0; i<subjs.length -1; i++) { //-1 caters for the last ";"
ty = subjs[i].split(":");
subjSel[i] = {licId:ty[0], subjId:ty[1], subjName:ty[2]};
}
//dropdown license
jQuery('#license#').change(function() {
$('#add').html(''); //clear the radios if any
val = $('input[name="license"]:checked').val();
var selectVals = "";
selectVals += '<select>';
for(var i=0; i<subjSel.length; i++) {
if(subjSel[i].licId == val) {
if(subjSel[i].subjId *1 == 9) continue;
selectVals += '<option value="'+subjSel[i].subjId+'">'+subjSel[i].subjName+'</option>';
}
}
selectVals += '</select>';
$("#subject").html(selectVals);
});
});
You seem to be asking two questions:
QUESTION 1. How to have a disabled select box (the second and third select boxes in the case of your example) which is activated upon the selection of an option from the first select box.
ANSWER 1:
simply use the disabled=true/false as below...
<select id="country" name="country" label="Country" onchange="document.getElementById('city').disabled=false; findCities(this.value)"/>
<select id="city" name="city" label="Location" disabled=true/>
NOTE: I changed "s:select" to "select" on the basis that your question does not make reference or tag the Struts framework that uses this syntax.
QUESTION 2: How to populate the second select box when a selection is made in the first.
ANSWER 2: There are many ways to do this, and the choice depends on where you have the data to populate the lists with. In the case of your Rentalcars example, if you chose Barbados, the browser sends an ajax GET request to "http://www.rentalcars.com/AjaxDroplists.do;jsessionid=5DCBF81333A88F37BC7AE15D21E10C41.node012a?country=Barbados&wrapNonAirports=true" -try clicking on this link and you will see what that request is sending back. This '.do' address is a server side file of a type used with the Struts framework I mentioned above.
A more conventional approach, which would be included in your function findCities(country)would be to send an AJAX request to a PHP script which queries a database and sends back an array of place names to the browser. The AJAX javascript code includes instructions as to what to do with the response. Without knowing more about where you want to store your list, giving an example of this would most likely not be useful.
Alternatively, the whole list of places could be included in the javascript script as an array (as demonstarated by Devima, above), in a text document on the server as comma separated values, or you could save it to a browser database like WebSQL or IndexedDB if offline use would be useful.
When you have got your list, probably as an array of values, you could save the array as a variable eg. var cities=result (in the case of a simple ajax request). You will then need to iterate through cities, for example
for (var i = 0; i < cities.length; i++){
var place=cities[i];//an individual city name
document.getElementById("city").innerHTML+="<option value='" + place + "'>" + place + "</option>";//adds an 'option' with the value being the city name and the text you see being the city name
}
IMO this is the base case AngularJS was designed to completely alleviate. Check it out!

Categories

Resources