dynamically created model undefined

I have the following custom field renderer:

'renderInitials': function (field, value) { value = skuid.utils.decodeHTML(value);<br>var nurseModel = skuid.$M('Nurses');<br>if (!nurseModel) {<br>var runCreateNurseModel = skuid.snippet.getSnippet('createNurseModel');<br>nurseModel = runCreateNurseModel();<br>}<br>if (field.mode === 'edit'){<br> &nbsp; &nbsp;var initials = [],<br> &nbsp; &nbsp; &nbsp; &nbsp;currentRN = value,<br> &nbsp; &nbsp; &nbsp; &nbsp;renderer = false,<br> &nbsp; &nbsp; &nbsp; &nbsp;userId = skuid.utils.userInfo.userId;<br> &nbsp; &nbsp;<br> &nbsp; &nbsp;//get options for initials picklist &nbsp; &nbsp;<br> &nbsp; &nbsp;<b>$.each(nurseModel.getRows()</b>, function(i, row){<br> &nbsp; &nbsp; &nbsp; &nbsp;initials.push({<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;value: row.Initials__c,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;label: row.Initials__c<br> &nbsp; &nbsp; &nbsp; &nbsp;});<br> &nbsp; &nbsp; &nbsp; &nbsp;if (!currentRN &amp;&amp; (row.Id == userId)) {currentRN = row.Initials__c}<br> &nbsp; &nbsp;});<br> &nbsp; &nbsp;<br> &nbsp; &nbsp;//determine if we should set the default initials<br> &nbsp; &nbsp;switch (field.id) {<br> &nbsp; &nbsp; &nbsp; &nbsp;case 'RN_Initials_for_Test__c' :<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;renderer = (field.model.getFieldValue(field.row, 'STD_Test_Method__c')) ? true : false;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp; &nbsp;case 'RN_Initials_for_Results__c' :<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;renderer = (field.model.getFieldValue(field.row, 'Results__c')) ? true : false;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp; &nbsp;case 'RN_Initials_for_Reporting_to_Patient__c' :<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;renderer = (field.model.getFieldValue(field.row, 'Results_Reported_to_Patient__c')) ? true : false;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp; &nbsp;case 'RN_Initials_Reporting_to_Health_Dept__c' :<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;renderer = (field.model.getFieldValue(field.row, 'Results_Reported_to_Health_Department__c')) ? true : false;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp; &nbsp;case 'RN_Initials_for_Treatment__c' :<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;renderer = (field.model.getFieldValue(field.row, 'STD_Treatment__c')) ? true : false;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp;}<br> &nbsp; &nbsp;<br> &nbsp; &nbsp;//render picklist<br> &nbsp; &nbsp;var customSelect = skuid.ui.renderers.PICKLIST.edit({<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;entries : initials,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;required : false,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;defaultValue : (renderer) ? currentRN : ''<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}).change(function() {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// &nbsp;Update the row in the target object<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;field.model.updateRow(field.row, field.id, $(this).val());<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;});<br> &nbsp; &nbsp;field.element.append(customSelect);<br>} else {<br> &nbsp; &nbsp;skuid.ui.fieldRenderers.TEXT[field.mode](field,value);<br>}<br>} 


If the ‘Nurses’ model doesn’t exist, I’m running this createNurseModel snippet to create it:

'createNurseModel': function() { <br>// Create dynamic model to capture nurse<br>nurseModel = new skuid.model.Model();<br>nurseModel.objectName = 'User';<br>nurseModel.id = 'Nurses';<br>nurseModel.fields = [<br> &nbsp; &nbsp;{ id: 'Id' },<br> &nbsp; &nbsp;{ id: 'Initials__c' }<br>];<br>nurseModel.orderByClause = 'Initials__c'<br>nurseModel.conditions = [<br> &nbsp; &nbsp;{&nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp;type: 'fieldvalue',&nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp;field: 'UserRole.Name',&nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp;operator: 'contains',&nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp;value: 'RN',<br> &nbsp; &nbsp; &nbsp; &nbsp;enclosevalueinquotes: true<br> &nbsp; &nbsp;}<br>];<br>nurseModel.initialize();<br>$.when(nurseModel.load())<br>.then(function(){<br>return nurseModel;<br>});<br>}


However, I’m getting the error that nurseModel is undefined when the field renderer tries to call getRows() on it in the $.each() in bold.

Is there something I’m missing here? Do I have to somehow get the field renderer snippet to wait until the createNurseModel snippet actually returns a model? And if so, how can I do that? Can I somehow return both a jQuery deferred promise and a model in the return statement after I create the model?

Your createNurseModel function doesn’t actually return anything so nurseModel will be undefined.  You could have the createNurseModel function return a promise instead.

nurseModel.initialize(); var myDeferred = new $.Deferred(); $.when(nurseModel.load()).then(function(){ myDeferred.resolve(nurseModel); }); return myDeferred.promise();


Then you would wait for your deferred to resolve in your custom renderer before rendering.

Ben,

I’m lost. What does

return nurseModel; 

do, if it’s not returning the model?


Should I use 

$.when(nurseModel.initialize().load())<br>.then(function(){<br>return nurseModel;<br>});

instead of

nurseModel.initialize();<br>$.when(nurseModel.load())<br>.then(function(){<br>return nurseModel;<br>});

???


Previously, I was returning a myDeferred.resolve() on $.when.done (but without nurseModel as an argument), and then trying to use skuid.$M() to get e reference to the model I just created. But it wasn’t working for me. skuid.$M() kept returning undefined.

Your return statement in the code above is the return value of the nested anonymous function, not the return value of the createNurseModel function.

You can learn more about the jQuery then() function here.

I think the reason skuid.$M() was not working is that you never registered your model.

try changing nurseModel.initialize() to nurseModel.initialize().register()


Ah, thanks for the explanation!

So, if I use

var myDeferred = new $.Deferred(); $.when(nurseModel.initialize().register().load()).then(function(){ myDeferred.resolve(nurseModel); }); return myDeferred.promise();

should createNurseModel() return the model along with the promise? Will the following lines in my field renderer code work?

var runCreateNurseModel = skuid.snippet.getSnippet('createNurseModel');<br>nurseModel = runCreateNurseModel();

Or should I still use skuid.$M() to get the model?

I’ve tried to read through the jQuery deferred documentation, but my brain is struggling…

I would do something like this…


var nurseModel = skuid.$M('Nurses'); var myActualRendering = function() { // Put all of your custom rendering code in here // This will only run when nurseModel is ready }; if (!nurseModel) { var runCreateNurseModel = skuid.snippet.getSnippet('createNurseModel'); var myAwesomePromise = runCreateNurseModel(); $.when(myAwesomePromise).then(function(resolvedModel){ // Either should work nurseModel = resolvedModel; // nurseModel = skuid.$M('Nurses'); // Do your rendering work here myActualRendering(); }); } else { // Do your rendering work here myActualRendering(); }<br>

Slick. That make sense!

Thanks for your help, Ben!