学习目标
- 创建一个窗体来显示当前值并接受新的用户输入。
- 从表单元素读取值。
- 验证用户输入并显示无效输入的错误消息。
- 将组件的控制器中的代码重构为其助手。
使用表单输入数据
就这个单元而言,我们完成了helloWhatever-style的组件。从这里开始,我们将创建和组装我们之前预览过的费用跟踪器迷你应用程序。我们将花费大部分的单位建设和理解的形式,让你创造一个新的开支。
费用应用程序容器
但是在开始之前,我们还需要做一些简单或者彻头彻尾的丑陋的组件。那么我们要做的第一件事就是引入Salesforce Lightning Design System或SLDS,并在我们的应用程序中“激活”它。我们这样做的方式让我们谈一谈关于应用程序容器。
<aura:application extends="force:slds">
<!-- This component is the real "app" -->
<!-- c:expenses/ -->
</aura:application>
应用程序组件的费用
下一步是创建我们的费用应用程序的顶级组件。 (请记住,尽管我们将其称为“应用程序”,但它实际上只是另一个Lightning组件)。在开发者控制台中,创建一个名为“费用”的新Lightning组件,并使用以下代码替换默认标记。
<aura:component>
<!-- PAGE HEADER -->
<lightning:layout class="slds-page-header slds-page-header--object-home">
<lightning:layoutItem>
<lightning:icon iconName="standard:scan_card" alternativeText="My Expenses"/>
</lightning:layoutItem>
<lightning:layoutItem padding="horizontal-small">
<div class="page-section page-header">
<h1 class="slds-text-heading--label">Expenses</h1>
<h2 class="slds-text-heading--medium">My Expenses</h2>
</div>
</lightning:layoutItem>
</lightning:layout>
<!-- / PAGE HEADER -->
<!-- 新的费用表格 -->
<lightning:layout>
<lightning:layoutItem padding="around-small" size="6">
<!-- [[ 费用表单在这里]] -->
</lightning:layoutItem>
</lightning:layout>
<!-- / NEW EXPENSE FORM -->
</aura:component>

现在还不是很多,但是看到SLDS造型已经有了效果,这真是令人兴奋。请记住,我们不会解释大部分SLDS标记,但我们将在标记中包含注释。你可以看到我们如何为应用程序创建标题,并开始获得这个想法。
新的费用表格
<!-- 创建新的费用 -->
<div aria-labelledby="newexpenseform">
<!-- BOXED AREA -->
<fieldset class="slds-box slds-theme--default slds-container--small">
<legend id="newexpenseform" class="slds-text-heading--small
slds-p-vertical--medium">
Add Expense
</legend>
<!-- 创建新的费用表格 -->
<form class="slds-form--stacked">
<lightning:input aura:id="expenseform" label="Expense Name"
name="expensename"
value="{!v.newExpense.Name}"
required="true"/>
<lightning:input type="number" aura:id="expenseform" label="Amount"
name="expenseamount"
min="0.1"
formatter="currency"
step="0.01"
value="{!v.newExpense.Amount__c}"
messageWhenRangeUnderflow="Enter an amount that's at least $0.10."/>
<lightning:input aura:id="expenseform" label="Client"
name="expenseclient"
value="{!v.newExpense.Client__c}"
placeholder="ABC Co."/>
<lightning:input type="date" aura:id="expenseform" label="Expense Date"
name="expensedate"
value="{!v.newExpense.Date__c}"/>
<lightning:input type="checkbox" aura:id="expenseform" label="Reimbursed?"
name="expreimbursed"
checked="{!v.newExpense.Reimbursed__c}"/>
<lightning:button label="Create Expense"
class="slds-m-top--medium"
variant="brand"
onclick="{!c.clickCreate}"/>
</form>
<!-- / 创建新的费用表单-->
</fieldset>
<!-- / BOXED AREA -->
</div>
<!-- / 创建新的费用 -->
这是由此产生的形式。

Salesforce对象的属性(sObject)
但首先,我们需要看看值属性。每个标签都有一个值,设置为一个表达式。例如,{!v.newExpense.Amount__c}。从表达的格式,你应该能够推断出一些东西。
- v表示这是视图值提供程序的属性。这意味着这是组件上的一个属性。 (我们还没有创建。)
- 基于点符号,你可以知道newExpense是某种结构化的数据类型。也就是说,newExpense本身具有属性。还是......字段?
- 从大多数属性名称末尾的“__c”中,您可以猜测这些映射回自定义字段,最有可能在费用自定义对象上。
- 所以,newExpense可能是一个费用对象!
很酷,我们还没有讨论这个呢!这里是实际的属性定义,您应该在打开<aura:component>标签之后添加到组件顶部。
<aura:attribute name="newExpense" type="Expense__c"
default="{ 'sobjectType': 'Expense__c',
'Name': '',
'Amount__c': 0,
'Client__c': '',
'Date__c': '',
'Reimbursed__c': false }"/>
在一个Action Handler中处理表单提交
({
clickCreate: function(component, event, helper) {
var validExpense = component.find('expenseform').reduce(function (validSoFar, inputCmp) {
// 显示无效字段的错误消息
inputCmp.showHelpMessageIfInvalid();
return validSoFar && inputCmp.get('v.validity').valid;
}, true);
// 如果我们通过错误检查,做一些真正的工作
if(validExpense){
// Create the new expense
var newExpense = component.get("v.newExpense");
console.log("Create expense: " + JSON.stringify(newExpense));
helper.createExpense(component, newExpense);
}
}
})
- 设置
- 处理表单值
- 如果没有错误,请做一些事情
- component.find('expenseform') 获取需要验证的<lightning:input>字段数组的引用。如果ID是唯一的,则引用返回组件。在这种情况下,ID不是唯一的,引用返回一个组件数组。
- JavaScript reduce()方法将数组减少为由validSoFar捕获的单个值,该值保持为真,直到找到无效字段,将validSoFar更改为false。无效字段可以是空的必填字段,具有低于指定最小数字的字段的字段等等。
- inputCmp.get('v.validity').valid返回数组当前输入字段的有效性。
- inputCmp.showHelpMessageIfInvalid() 显示无效字段的错误消息。 <lightning:input>提供了默认的错误消息,可以通过messageWhenRangeUnderflow等属性进行自定义,您可以在费用表单中看到该消息。
- 不要试图创造费用。
- 显示有用的错误消息。
创建新的费用
<aura:attribute name="expenses" type="Expense__c[]"/>
- 组件的帮助程序是将代码在几个不同的操作处理程序之间共享的合适位置。
- 组件的帮助程序是放置复杂的处理细节的好地方,所以您的操作处理程序的逻辑保持清晰和精简。
- 助手功能可以有任何功能签名。也就是说,它们不受控制器中动作处理程序的限制。 (这是为什么呢?因为你直接从你的代码中调用helper函数,相反,框架通过框架运行时调用动作处理函数。)这是一个约定和推荐的做法,总是提供组件作为帮助函数的第一个参数。
好吧,让我们继续吧。在开发人员控制台中,单击费用组件的HELPER按钮以创建关联的助手资源,然后将示例代码替换为以下内容。
({
createExpense: function(component, expense) {
var theExpenses = component.get("v.expenses");
//将费用复制到一个新的对象这是一个令人讨厌的,暂时的黑客
var newExpense = JSON.parse(JSON.stringify(expense));
theExpenses.push(newExpense);
component.set("v.expenses", theExpenses);
}
})
参考不是收集
console.log("创建之前的开支: " + JSON.stringify(theExpenses));
theExpenses.push(newExpense);
component.set("v.expenses", theExpenses);
console.log("创建后的费用: " + JSON.stringify(theExpenses));
显示费用列表
<aura:component>
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<aura:attribute name="formatdate" type="Date"/>
<aura:attribute name="expense" type="Expense__c"/>
<lightning:card title="{!v.expense.Name}" iconName="standard:scan_card"
class="{!v.expense.Reimbursed__c ?
'slds-theme--success' : ''}">
<aura:set attribute="footer">
<p>Date: <lightning:formattedDateTime value="{!v.formatdate}"/></p>
<p class="slds-text-title"><lightning:relativeDateTime value="{!v.formatdate}"/></p>
</aura:set>
<p class="slds-text-heading--medium slds-p-horizontal--small">
Amount: <lightning:formattedNumber value="{!v.expense.Amount__c}" style="currency"/>
</p>
<p class="slds-p-horizontal--small">
Client: {!v.expense.Client__c}
</p>
<p>
<lightning:input type="toggle"
label="Reimbursed?"
name="reimbursed"
class="slds-p-around--small"
checked="{!v.expense.Reimbursed__c}"
messageToggleActive="Yes"
messageToggleInactive="No"
onchange="{!c.clickReimbursed}"/>
</p>
</lightning:card>
</aura:component>
({
doInit : function(component, event, helper) {
var mydate = component.get("v.expense.Date__c");
if(mydate){
component.set("v.formatdate", new Date(mydate));
}
},
})
<aura:component>
<aura:attribute name="expenses" type="Expense__c[]"/>
<lightning:card title="Expenses">
<p class="slds-p-horizontal--small">
<aura:iteration items="{!v.expenses}" var="expense">
<c:expenseItem expense="{!expense}"/>
</aura:iteration>
</p>
</lightning:card>
</aura:component>
<c:expensesList expenses="{!v.expenses}"/>