Link to home
Start Free TrialLog in
Avatar of Isaac
IsaacFlag for United States of America

asked on

JSON javaScript form

Hi All,

I am trying to do some things with JSON that I have coded in jsfiddle.  When "PROJ123" is entered into the "Project Number" field, the "Plan Number" drop down box gets populated with corresponding values.  When it gets populated though, I want the default value to be blank.  How do I do that?

Also, I want the corresponding contract type to populate <span id="contractType"></span> based on the "Plan Number" selected.
Here's how to get the contract type Contracts[x].Plan.Info.ContractType from JSON.

<table border="1" width="65%" style="background-color:#eeeeee">
  <tr style="background-color:#00558D;color:white;font-weight:bold;font-size:14px">
    <td colspan="4">New Contract</td>
  </tr>

  <tr>
  	<td>Project Number</td>
  	<td colspan="3"><input type="text" value="" id="projectNumber"></td>
  </tr>

  <tr>
  	<td>Plan Number</td>
  	<td colspan="3">
  		<select id="planNumber">
  			<option value=""></option>
  		</select><span id="contractType"></span>
  	</td>
  </tr>

Open in new window



function getPlanNumbers(projNumber){
$("#planNumber").empty();

var planNumber = [];
var y=0;
var pNumOption = document.getElementById("planNumber");

for (var x=0; x<jsonFile.Result.Contracts.length; x++){
//alert(jsonFile.Result.Contracts[x].Plan.Info.ProjectNumber);
if (jsonFile.Result.Contracts[x].Plan.Info.ProjectNumber === projNumber){
planNumber.push(jsonFile.Result.Contracts[x].Plan.Identification.PlanNumber);
}else{
y++;
}
}
if (jsonFile.Result.Contracts.length == y){
alert("Project Number '"+ projNumber + "' does not exist.");
}else{
for(var i=0; i<planNumber.length; i++){
var option = document.createElement('option');
                                
option.value = planNumber[i];
option.innerHTML = planNumber[i];
                                   
pNumOption.appendChild(option);
}

}

// alert("populate dropdown");
}

Open in new window


The actual JSON can be found at this jsfiddle with the rest of the code.
https://jsfiddle.net/isogunro/03y6zwbe/
Avatar of HainKurt
HainKurt
Flag of Canada image

added

planNumber.push("");

Open in new window


to line 565

https://jsfiddle.net/HainKurt/km91869q/
ASKER CERTIFIED SOLUTION
Avatar of HainKurt
HainKurt
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@Julian

The second part of your request would be to add the following to your document ready

I guess Contract type should come from json

var jsonFile =     {"Result": {
"Contracts": [
{
"Plan": {
"Identification": {
"PlanNumber": "8930-3o3pp"
},
"Info": {
"Title": "chjdj",
"ProjectNumber": "PROJ123",
"StationCode": "STATIONCD1",
"ContractType": "Commodities",
"ActionType": "chvj-PLAN"
},

Open in new window


which I used in my solution above...
@HK - thank you for the clarification

However I would do it like this. I would associate the contractType with the option and retrieve that on the change event rather than iterating over the data set each time
function getPlanNumbers(projNumber)
{
  $("#planNumber").empty();
  
  // CREATE DEFAULT OPTION HERE
  $('#planNumber').append($('<option>').html('-- Select Project--'));
  
  // USE map() TO ITERATE OVER JSON FILE
  var results = jsonFile.Result.Contracts.map(x => {
    // IF projNumber MATCH THEN APPEND <option>
    if (x.Plan.Info.ProjectNumber == projNumber) {
      var opt = $('<option>')
        .html(x.Plan.Identification.PlanNumber)

        // ASSOCIATE THE contractType WITH THE <option>
        .data('contractType', x.Plan.Info.ContractType);
      
      $("#planNumber").append(opt);
    }
  });
}

Open in new window


Then to set the contractType
$("#planNumber").on("change", function(){
   var obj = $(this).find('option:selected');
   $('#contractType').html(obj.data('contractType'));     
});

Open in new window

@Julian

I would associate the contractType with the option and retrieve that on the change event rather than iterating over the data set each time

I thought the same thing, but I was a bit lazy :) Also, I was trying to minimize the change in original code... just addition if possible...

But, here is the code adjusted version and using the same method you used in your code...
ie, adding "data-ContractType='....'" to the option and use that one on change...

function getPlanNumbers(projNumber) {
  $("#planNumber").empty();

  var planNumber = [];
  var y = 0;
  var pNumOption = document.getElementById("planNumber");
  planNumber.push(["", ""]);
  for (var x = 0; x < jsonFile.Result.Contracts.length; x++) {
    //alert(jsonFile.Result.Contracts[x].Plan.Info.ProjectNumber);
    if (jsonFile.Result.Contracts[x].Plan.Info.ProjectNumber === projNumber) {
      planNumber.push([jsonFile.Result.Contracts[x].Plan.Identification.PlanNumber, jsonFile.Result.Contracts[x].Plan.Info.ContractType]);
    } else {
      y++;
    }
  }
  if (jsonFile.Result.Contracts.length == y) {
    alert("Project Number '" + projNumber + "' does not exist.");
  } else {
    console.log(planNumber)
    for (var i = 0; i < planNumber.length; i++) {
      var option = $('<option>');

      option.val(planNumber[i][0]);
      option.html(planNumber[i][0]);
      option.data("ContractType", planNumber[i][1]);
      console.log("adding: " + planNumber[i][0] + " - " + planNumber[i][1]);
      console.log(option);
      $("#planNumber").append(option);
    }

  }

  // alert("populate dropdown");
}

$("#projectNumber").on("change", function() {
  var projectNumber = $("#projectNumber").val();
  //alert("projectNumber: " + projectNumber);
  getPlanNumbers(projectNumber);
});

$("#planNumber").on("change", function() {
  var projectNumber = $("#projectNumber").val();
  //alert("projectNumber: " + projectNumber);
  var planNumber = $("#planNumber").val();
  //alert("planNumber: " + planNumber);
  var ct = $("#planNumber option:selected").data('ContractType');
  console.log($("#planNumber option:selected"))
  $("#contractType").html(ct);
  //getPlanNumbers(projectNumber);
});

Open in new window


https://jsfiddle.net/HainKurt/phs3fm8y/
Avatar of Isaac

ASKER

Both codes work great in jsfidel but for some reason,  I get syntax error on Julian's code on the following line:

  var results = jsonFile.Result.Contracts.map(x => {

Open in new window

Avatar of Isaac

ASKER

I get the error when I try to actually add it to my test site.  Trying Hainkurt's now
Both codes work great in jsfidel but for some reason,  I get syntax error on Julian's code on the following line:

works fine...

see

https://jsfiddle.net/HainKurt/73m22y9t/
https://jsfiddle.net/HainKurt/z6f33doy/
The server makes no difference to the map() function as this runs in your browser - so you probably have a typo. Can you post your full code please
Avatar of Isaac

ASKER

As I'm looking at both codes and trying to understand while googling, I get stumped as to both codes reference 'contractType'.  I don't see a reference to it like so  $('#contractType').  

Ex: Julian's code
How does that associate?  Is that a new way to do $('#contractType')?
      // ASSOCIATE THE contractType WITH THE <option>
      .data('contractType', x.Plan.Info.ContractType);

Open in new window


HainKurt's code
var ct = $("#planNumber option:selected").data('ContractType');  //<-- This confused me.  .data()??
  console.log($("#planNumber option:selected"))
  $("#contractType").html(ct);

Open in new window

they add data attribute to option

<option data-contractType="Contributor">vat-3o3pp</option>

Open in new window


and when selected, we get it and put into html...

.data()
Store arbitrary data associated with the matched elements or return the value at the named data store for the first element in the set of matched elements.
https://api.jquery.com/data/
How does that associate?  Is that a new way to do $('#contractType')?
No you are mixing up selecting an element with adding properties to an element.

What I am doing in my code here

.data('contractType', x.Plan.Info.ContractType);

Open in new window


Is as we iterate over the JSON structure finding our Project Plan Numbers we might as well grab the contractType while we are there.

We now add this to the element using the HTML5 dataset functionality (implemented in jQuery using the data() method).

What this does is associates a custom data value with the element which will follow the element wherever it goes.

When we get to the part where you actually select a projectPlan from the dropdown - the contratType is already there - attached to the option it belongs to - you simply retrieve it and push it into the element you want to display it.

EDIT
Remember, in JavaScript you can arbitrarily add properties (and methods) to objects just by declaring and assigning them. HTML elements are represented as JavaScript objects in the DOM so you can arbitrarily add properties (or functions) to elements and they will become part of the object in the DOM tree - you can then access those values at any time. This allows you to associate meta data with elements that you might need when that element is selected or acted upon.
Avatar of Isaac

ASKER

That makes a lot of sense.  It just gave me an idea.  I'm working on how to capture the index of the selected plan number.
Did you see my inbox message?
The index - would that be the index relative to the <option> list or the index in the JSON structure?

If the latter then you can use the same principle as for the contractType to attach the index to the <option> and then retrieve it when you need it.