function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
narsavagepnarsavagep 

Javascript Referencing Input Cell In Iterative Component

I have a VF page which lists several objects at once and allows the user to update them and hit a "save" button.  When the user edits one of the fields, I want a javascript call to populate something in another field.  How do I reference the appropriate field in the action command?

 

Below is the example of what I'm looking to do.

 

<apex:pageBlockSection title="New Case Dates" columns="1" collapsible="false" showHeader="true">
    <apex:pageBlockTable value="{!CasesToCreate}" var="case">
        <apex:column headerValue="Commit">
            <apex:inputField value="{!case.Commit_Date__c}" onchange="UpdateReleaseText(this.value, ReleaseTextId?);"/>
        </apex:column>
        <apex:column headerValue="Release">
            <apex:inputField value="{!case.Release__c}" id="ReleaseText"/>
        </apex:column>
    </apex:pageBlockTable>
</apex:pageBlockSection>

 

 

 

Thanks!

Paul

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

Hmmm.  That is quite tricky.

 

It looks like getUniqNum may get rationalised to a single replacement when the page is rendered.

 

Presumably you are creating a list of cases?  That being the case(!) you could bring a wrapper class into the equation and combine the unique id with the case and return a list of those.

 

Something like:

 

 

public class CaseWrapper()
{
   public Integer id {get; set;}
   public Case wrappedCase {get; set;}

   public CaseWrapper(Integer inId, Case inCase)
   {
      id=inId;
      wrappedCase=inCase;
   }
}


// and where you create your list of cases, do:
public List<CaseWrapper> getCasesToCreate()
{
   List<CaseWrapper> result=new List<CaseWrapper>();
   for (Integer loop=0; loop<6; loop++)
   {
      result.add(new CaseWrapper(loop, new Case());
   }

   return result;
}

 Then in your page you'd iterate the wrapper list:

 

 

<apex:pageBlockTable value="{!CasesToCreate}" var="caseWrap">
        <apex:column headerValue="Commit">
            <apex:inputField value="{!caseWrap.wrappedCase.Commit_Date__c}" ...

 

 

 

All Answers

bob_buzzardbob_buzzard

You'll need to generate an id that is unique to the particular instance that your pageblocktable is processing.

 

As you are using case sobjects, can you use the sobject id?  Something like:

 

 

<apex:pageBlockSection title="New Case Dates" columns="1" collapsible="false" showHeader="true">
    <apex:pageBlockTable value="{!CasesToCreate}" var="case">
        <apex:column headerValue="Commit">
            <apex:inputField value="{!case.Commit_Date__c}" onchange="UpdateReleaseText(this.value, 'reltext-{!case.id}');"/>
        </apex:column>
        <apex:column headerValue="Release">
            <apex:inputField value="{!case.Release__c}" id="reltext-{!case.id}"/>
        </apex:column>
    </apex:pageBlockTable>
</apex:pageBlockSection>

 

 

narsavagepnarsavagep

Thanks Bob...

 

Good idea... however, I get the following error if I try to do that:

 

Literal value is required for attribute id in <apex:inputField> in Case_DP_Clone at line 65 column 65
Paul

 

bob_buzzardbob_buzzard

Bummer.

 

I've just checked back how I did something similar.  

 

I wrapped my components in a vanilla HTML span tag, which can take a dynamically generated id.  My javascript then located the span, found the input element inside that and populated its value.  There's obviously some compromise there, in that you are assuming the particular type of input element (e.g. select, textarea etc), but that wasn't an issue for me.

narsavagepnarsavagep

OK, that makes sense.

Do you happen to have the javascript code that you could post a snippet of if?  Just to make development time for me quicker/easier.  If not, I understand.

Thanks so much for your input.

 

Paul

bob_buzzardbob_buzzard

It wouldn't be much use I'm afraid, as it was part of a Dojo drag and drop event handler and the logic was split over about four methods.

narsavagepnarsavagep

OK, I'm getting there... my current issue is trying to get a unique number/identifier for each row.  

I'm creating six new cases for these six rows that I'm working with, but they are not actually "inserted" into the database at the time the VF page is created -- as the user needs to populate the dates, hit submit, and then the cases are created.  So there is no "Case.Id" for the rows.  *sigh*

 

I tried creating a unique number, but these functions in the controller are always returning "1" -- never incrementing.  

 

private Integer UniqNum = 0;
public Integer getUniqNum() {
	return UniqNum;	
}
public Integer getNewUniqNum() {
	UniqNum++;
	return UniqNum;	
}

When I call {!NewUniqNum} on the VF page, I get "1" for every row... it's not incrementing??

 

What am I missing here?

 

Thanks!

bob_buzzardbob_buzzard

Hmmm.  That is quite tricky.

 

It looks like getUniqNum may get rationalised to a single replacement when the page is rendered.

 

Presumably you are creating a list of cases?  That being the case(!) you could bring a wrapper class into the equation and combine the unique id with the case and return a list of those.

 

Something like:

 

 

public class CaseWrapper()
{
   public Integer id {get; set;}
   public Case wrappedCase {get; set;}

   public CaseWrapper(Integer inId, Case inCase)
   {
      id=inId;
      wrappedCase=inCase;
   }
}


// and where you create your list of cases, do:
public List<CaseWrapper> getCasesToCreate()
{
   List<CaseWrapper> result=new List<CaseWrapper>();
   for (Integer loop=0; loop<6; loop++)
   {
      result.add(new CaseWrapper(loop, new Case());
   }

   return result;
}

 Then in your page you'd iterate the wrapper list:

 

 

<apex:pageBlockTable value="{!CasesToCreate}" var="caseWrap">
        <apex:column headerValue="Commit">
            <apex:inputField value="{!caseWrap.wrappedCase.Commit_Date__c}" ...

 

 

 

This was selected as the best answer
narsavagepnarsavagep

Brilliant!!

Thanks so much!


For future reference, and if anyone else is looking for same/similar solution... here's snippets of the code I ended-up with that works great.

 

Page:

 

<apex:pageBlockTable value="{!CasesToCreate}" var="cw">
  <apex:column headerValue="Commit">
    <apex:inputField value="{!cw.wrappedCase.Commit_Date__c}" id="CommitDate" onChange="UpdateReleaseText(this,'Row{!cw.uniqNum}')"/>
  </apex:column>
  <apex:column headerValue="Release">
    <div id="Row{!cw.uniqNum}">
      <apex:inputField value="{!cw.wrappedCase.Release__c}" id="ReleaseText"/>
    </div>
  </apex:column>
</apex:pageBlockTable>

 Page Javascript&colon;

 

<script language="JavaScript">
    
    var MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];
    
    function UpdateReleaseText( objDate, rowId ) {
    
		var objRelease;
		var elmSpan = document.getElementById(rowId).getElementsByTagName('input');
		for (var i = 0; i < elmSpan.length; i++) {
			if ( elmSpan[i].type == "text" ) objRelease = elmSpan[i]; 
		}
		//if (objRelease) objRelease.value = objDate.value;
		if ( objRelease && objDate.value.trim().length > 0 ) {
			releaseTxt = '';
			var tokens = objDate.value.split("/");
			if (tokens.length == 3) releaseTxt = MONTHS[(tokens[0]-1)] + ' ' + tokens[2];
			objRelease.value = releaseTxt;
		}
	}

</script>

 Controller:

 

...

private static Integer MaxNumOfClones = 6;

public class CaseWrapper {
   public Integer uniqNum {get; set;}
   public Case wrappedCase {get; set;}

   public CaseWrapper (Integer inUniqNum, Case inCase) {
      uniqNum = inUniqNum;
      wrappedCase = inCase;
   }
}

public List<CaseWrapper> CasesToCreate { get; set; }

...

// Within Controller Initiation
CasesToCreate = new List<CaseWrapper>();
for (Integer i=0; i<MaxNumOfClones; i++) {
   CasesToCreate.add( new CaseWrapper(i, CloneCase(RefCase) ));
}

 

 

 

 

Thanks again so much!

Paul

 

narsavagepnarsavagep

PS: The code above shows a date field (we call "commit") and a text field (we call "release").

The javascript populates the release field with the month and year of the selected commit date.  (ie "February 2011")

(The release text can then be modified by the user if they wish.)