[SalesForce] Elegant initialization of Lightning aura:attribute

The expense tracker app from the Lightning Components Developer's Guide shows the following markup for initializing an sObject attribute.

<aura:attribute name="newExpense" type="namespace.Expense__c"
                default="{
                             'sobjectType': 'namespace__Expense__c',
                             'Name': '',
                             'namespace__Amount__c': 0,
                             'namespace__Client__c': '', 
                             'namespace__Date__c': '',
                             'namespace__Reimbursed__c': false
                         }"/>

Is there a better way to initialize an sObject attribute like newExpense? Specifically, a way to initialize the attribute without manually having to explicitly initialize every single field which will be taking user input?

In Visualforce, all I had to do was construct a new sObject, such as Lead theLead = new Lead(); and then return that object via a property. I'm hoping there a similarly simple approach I can apply to initializing attributes in Lightning.

Best Answer

In Winter '15, it seems that all fields that will be data-bound need to be explicitly initialized in the default attribute. In situations where I don't want to go through the hassle of explicitly defining every single field, I've adopted a pattern of using an Apex controller method to return a new instance of the desired object that has default values filled in.

@AuraEnabled
public static Contact newContact() {
    return (Contact)Contact.sObjectType.newSObject(null, true);
}

With this method defined, I use an init handler to invoke the Apex controller method, and then store the result in the desired variable. Below is a helper function definition that I call from the init handler.

initThisContact : function(component) {
    var self = this;  // safe reference

    // Create an action to invoke the Apex controller method
    // which will return a new Contact record
    var initAction = component.get("c.newContact");
    initAction.setCallback(self, function(a) {
        component.set("v.thisContact", a.getReturnValue());
    });

    // Enqueue the action
    $A.enqueueAction(initAction);
}

This approach is not as efficient as being able to simply initialize a new object via the default attribute, since it requires a round-trip Ajax request to Salesforce. I hope in the future there will be a more efficient way to initialize sObject attributes in Lightning.