Snippet For Create New Child Object Using Master Field Values?

  • 1
  • Question
  • Updated 3 years ago
  • Answered
I'm getting over my head with the Java snippet stuff and field renderers but feel like this might be doable based on comments, but I'm not getting it and want to ensure I'm not wasting my time.

I have Master Detail relationship and want to create a new detail record using mobile. The Master object (Questions) are questions and picklist values with acceptable responses (i.e. Yes, No). On the detail object (Answers) all of the response fields are text. I want the response field to be a picklist from the acceptable answers in the Master object. So:

Master Question 1 - "Are you tall?" - Acceptable answers "Yes/No"
Detail Response 1 - (Field is text) I want display options for mobile user to be "Yes/No".

I could live with having to hardcode the acceptable responses vs reading them from Master (better).
Photo of ddeveaux

ddeveaux

  • 1,202 Points 1k badge 2x thumb

Posted 4 years ago

  • 1
Photo of Moshe Karmel

Moshe Karmel, Champion

  • 8,646 Points 5k badge 2x thumb
It can definitely be done. Can you post what you've built so far? I'll try to fill in the missing parts.
Photo of ddeveaux

ddeveaux

  • 1,202 Points 1k badge 2x thumb
This code does render a picklist field for the 1st response, but there are no values populated. I was trying to use a few of the examples here but not quite getting there.

One piece I'm also confused about is, since I'm creating a detail record should the reference be "Detail__r.Master_Field1" or just "Master_Field1". It looks like since the record isnt' created yet and this is an entry screen that I have to use "Master_Field1"?


var auditsettingmodel = skuid.model.getModel('AuditSetting'),audrow = auditsettingmodel.getFirstRow();

var field = arguments[0],
    value = arguments[1],
    $ = skuid.$;

var choices = field.model.getFieldValue(field.audrow,'ONE__Q1_Answer_Choices__c');

if (field.mode == 'edit')
{
        skuid.ui.fieldRenderers['PICKLIST'].edit(field,value);
}
Photo of Moshe Karmel

Moshe Karmel, Champion

  • 8,646 Points 5k badge 2x thumb
var auditsettingmodel = skuid.model.getModel('AuditSetting'),	
audrow = auditsettingmodel.getFirstRow();
var field = arguments[0],
    value = arguments[1],
    $ = skuid.$;
//I'm assuming that this field contains the picklist values
var choices = field.model.getFieldValue(field.audrow,'ONE__Q1_Answer_Choices__c');
//check what you're getting in the console (Ctrl + Shift + J in Chrome)
console.log(choices);
if (field.mode == 'edit'){
//you probably want the second value to be choices, which would be the values from the master object
    skuid.ui.fieldRenderers['PICKLIST'].edit(field, choices);
}

//where do you want to create a new row? Does the user click a button?
//creating a new row would look something like this...
//this is just to give you an idea - don't put this in the actual snippet...
childModel.createRow({
additionalConditions: [
{field: 'Reference_Field__c', value: masterRow.Id, nameFieldValue: masterRow.Name},
        {field:'Random_Field__c', value: 'Whatever you want '}
]
});
Photo of Moshe Karmel

Moshe Karmel, Champion

  • 8,646 Points 5k badge 2x thumb
Can you describe the process in greater detail? 
1. User clicks a button
2. New row gets created, etc.
Photo of ddeveaux

ddeveaux

  • 1,202 Points 1k badge 2x thumb
I'll drop your code and and see if I can play with it. I'm moderately comfortable reading code so can sometimes get the logic and adjust as needed...sometimes.

I'm using mobile, though also going to make desktop page.

1. User selects a Contact from a list

2. Contact Id is sent to next model which displays relevant ContactAddresses. Junction object that will now only display Addresses for that Contact. User selects appropriate one.

3. Id from Junction now passed into 3rd model. User presented with an edit screen to create a new survey. The survey will be attached to the record selected in Step 2. The Survey object is Detail to M-D relationship with Questions object (M). So as user swipes, clicks through screen the relevant questions from the Master object appear "Did person have nametag?" The Master object also has a field for each question with picklist values for the possible responses (Yes, No). As user swipes to each question, we want a mobile friendly way to select from the possible picklist values and capture those as responses to the questionnaire. All response fields are text as mentioned before.

Note: The response fields are text because this application is used via another API where the relationship I describe above makes sense. This is why the response fields are not picklist. (Plus there are many many different Master question templates so sometimes the possible responses to Q1 might be "Yes, No", othertimes "1,2", etc.
Photo of ddeveaux

ddeveaux

  • 1,202 Points 1k badge 2x thumb
Looks like Console returning null. I know the first row is returning values because I have the Question and Response choices displaying in a panel on same page for user right now. Also have warning message in Console,

"Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/."
Photo of Moshe Karmel

Moshe Karmel, Champion

  • 8,646 Points 5k badge 2x thumb
Don't worry about the XML warning, that's nothing. The fact that it is returning null, is because you have field.audrow, when it should really be field.row. What model and field is your snippet on?
Photo of ddeveaux

ddeveaux

  • 1,202 Points 1k badge 2x thumb
Snippet is on AuditReport model. It will eventually be on all 20 possible response fields but for now I've been trying it on ONE__Response_1__c.

I changed the field.row value. Still seemed to get null. I'm going to get lunch and will look at when return. Thanks for help thus far!
(Edited)
Photo of Moshe Karmel

Moshe Karmel, Champion

  • 8,646 Points 5k badge 2x thumb
Sorry you also had the wrong model, try this:

var field = arguments[0],    value = arguments[1],
    $ = skuid.$;
console.log(value);
var auditSettingModel = skuid.model.getModel('AuditSetting'),
audRow = auditSettingModel.getFirstRow();
//I'm assuming that this field contains the picklist values
var choices = auditSettingModel.getFieldValue(audRow,'ONE__Q1_Answer_Choices__c');
//check what you're getting in the console (Ctrl + Shift + J in Chrome)
console.log(choices);
if (field.mode == 'edit'){
//you probably want the second value to be choices, which would be the values from the master object
    skuid.ui.fieldRenderers['PICKLIST'].edit(field, choices);
}
Photo of ddeveaux

ddeveaux

  • 1,202 Points 1k badge 2x thumb
Looks and feels like this should be working but it's not. The console shows the correct values for variable choices (Yes;No) but the renderer just shows a "--None--" picklist option. I tried a few other picklist fields in its place and same results.
Photo of Moshe Karmel

Moshe Karmel, Champion

  • 8,646 Points 5k badge 2x thumb
OK let's try something a little different. Try using this snippet below. It basically creates a picklist from scratch and attaches it to the fields DOM element. Keep a sharp eye on the console.

var field = arguments[0],    value = skuid.utils.decodeHTML(arguments[1]),
   $ = skuid.$;
var auditSettingModel = skuid.model.getModel('AuditSetting'),
audRow = auditSettingModel.getFirstRow();
//I'm assuming that this field contains the picklist values
//I'm also assuming that they are separated by ";"
var choices = auditSettingModel.getFieldValue(audRow,'ONE__Q1_Answer_Choices__c');
//check what you're getting in the console (Ctrl + Shift + J in Chrome)
console.log(choices);
//split the list of choices into an array
var semiColonSplit = choices.split(";");
//check what you're getting in the console (Ctrl + Shift + J in Chrome)
console.log(semiColonSplit);
//add all of the elements in the array as options in our picklist if we're in edit mode
if(field.mode === 'edit'){
    var customOpts = [];
    $.each(semiColonSplit, function(elem){
    console.log(elem);
customOpts.push({
value: elem,
label: elem
});
});
    //Render the options as a PICKLIST
    var customSelect = skuid.ui.renderers.PICKLIST.edit({
        entries : customOpts,
        required : true,
        value : value
    });
    //Append the PICKLIST to the DOM element
    field.element.append(customSelect);
}else{
    skuid.ui.fieldRenderers.INTEGER[field.mode](field,value);
}
Photo of ddeveaux

ddeveaux

  • 1,202 Points 1k badge 2x thumb
Up to semiColonSplit values are ok in log. Then the array elements become 0 and 1, instead of Yes and No. If I add a 3rd picklist value same thing but array is populated with 0, 1, 2 vs actual values. So picklist shows 0,1,2.

Seems like the issue is "$.each(semiColonSplit, function(elem){"?
Photo of Moshe Karmel

Moshe Karmel, Champion

  • 8,646 Points 5k badge 2x thumb
OK try it now, I added a second parameter to the for loop:

var field = arguments[0],    value = skuid.utils.decodeHTML(arguments[1]),
   $ = skuid.$;
var auditSettingModel = skuid.model.getModel('AuditSetting'),
audRow = auditSettingModel.getFirstRow();
//I'm assuming that this field contains the picklist values
//I'm also assuming that they are separated by ";"
var choices = auditSettingModel.getFieldValue(audRow,'ONE__Q1_Answer_Choices__c');
//check what you're getting in the console (Ctrl + Shift + J in Chrome)
console.log(choices);
//split the list of choices into an array
var semiColonSplit = choices.split(";");
//check what you're getting in the console (Ctrl + Shift + J in Chrome)
console.log(semiColonSplit);
//add all of the elements in the array as options in our picklist if we're in edit mode
if(field.mode === 'edit'){
    var customOpts = [];
    $.each(semiColonSplit, function(i,elem){
    console.log(elem);
customOpts.push({
value: elem,
label: elem
});
});
    //Render the options as a PICKLIST
    var customSelect = skuid.ui.renderers.PICKLIST.edit({
        entries : customOpts,
        required : true,
        value : value
    });
    //Append the PICKLIST to the DOM element
    field.element.append(customSelect);
}else{
    skuid.ui.fieldRenderers.PICKLIST[field.mode](field,value);
}
Photo of ddeveaux

ddeveaux

  • 1,202 Points 1k badge 2x thumb
Bingo! That seems to work! I at least see those values in the field, I haven't gone so far as saving but I should be good there! Since this was more code to achieve this than I expected, do you think it will be a performance issue at all to have 4-5 of these in each panel since I was displaying 4-5 questions each...total of 20.

Thanks a lot for all of your work here! I'll owe you something at DF15...assuming you are going. I registered this morning for my 6th.
Photo of Moshe Karmel

Moshe Karmel, Champion

  • 8,646 Points 5k badge 2x thumb
There's is one more thing to do here. In order for your changes to be applied to the actual field, you have to add the following "on change" function. Thanks for the accolades I may just be at DreamForce this year!

var field = arguments[0],    value = skuid.utils.decodeHTML(arguments[1]),
   $ = skuid.$;
var auditSettingModel = skuid.model.getModel('AuditSetting'),
audRow = auditSettingModel.getFirstRow();
//I'm assuming that this field contains the picklist values
//I'm also assuming that they are separated by ";"
var choices = auditSettingModel.getFieldValue(audRow,'ONE__Q1_Answer_Choices__c');
//check what you're getting in the console (Ctrl + Shift + J in Chrome)
console.log(choices);
//split the list of choices into an array
var semiColonSplit = choices.split(";");
//check what you're getting in the console (Ctrl + Shift + J in Chrome)
console.log(semiColonSplit);
//add all of the elements in the array as options in our picklist if we're in edit mode
if(field.mode === 'edit'){
    var customOpts = [];
    $.each(semiColonSplit, function(i,elem){
    console.log(elem);
customOpts.push({
value: elem,
label: elem
});
});
    //Render the options as a PICKLIST
    var customSelect = skuid.ui.renderers.PICKLIST.edit({
        entries : customOpts,
        required : true,
        value : value
    }).change(function(){//this handle the updates to the field the renderer is on
field.model.updateRow(field.row, field.id, skuid.$(this).val(),{
initiatorId: field._GUID
});
});
    //Append the PICKLIST to the DOM element
    field.element.append(customSelect);
}else{
    skuid.ui.fieldRenderers.PICKLIST[field.mode](field,value);
Photo of Moshe Karmel

Moshe Karmel, Champion

  • 8,646 Points 5k badge 2x thumb
Photo of ddeveaux

ddeveaux

  • 1,202 Points 1k badge 2x thumb
I've not done too much with Banzai yet but do you know if this is at all made simpler with Banzai? On the mobile side I've had a few users with some issues, especially one that has an iPhone 4S. She says Javascript is enabled but the picklists have never rendered for her. Love to see if any native methods for this have popped up since last release?
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,006 Points 20k badge 2x thumb
I wouldn' look first at the javascript.  Cuz if javascfript is not working on the phone - most ALL skuid is going to be busted.  Having said that - I don't think direct changes in banzai will make your code unnecessary.  There may be changes that make it more efficient, but I can't promise that.