Salesforce視圖與控制器之間的交互


剛接觸Salesforce,過程的確是比較艱難了,中文資料幾乎沒有,看英文資料學的效率卻不高,不過看了一段時間的英文資料發現自己英語水平挺高不少啊,現在看都不用工具翻譯,早知道就再次嘗試報個6級,看下能過不,嘻嘻。。。。Salesforce的開發也是MVC模式,asp.net的MVC就玩的比較多了,換個平台一下子沒適應過來,不過原理都一樣,接下來就介紹一下最近的學習成果吧,來看一下SF中MVC模式下視圖與控制器之間的交互,先貼控制器和視圖的代碼,下面有詳細講解。

apex視圖代碼如下:

<apex:page Controller="SendMessageController">
<apex:stylesheet value="{!URLFOR($Resource.jQuery,  'jquery-ui.css')}" />
    <apex:stylesheet value="{!URLFOR($Resource.jQuery,  'mystyle.css')}" />
    <apex:includeScript value="{!URLFOR($Resource.jQuery, 'jquery-2.1.1.min.js')}"/>
    <apex:includeScript value="{!URLFOR($Resource.jQuery, 'jquery-ui.js')}"/>
<apex:form >
  <apex:pageBlock title="視圖與控制器的交互">
    <apex:pageBlockSection title="Ajax請求提示區">
    <apex:outputPanel >
        <apex:actionStatus startStyle="font-size:40px;color:red;" stopStyle="font-size:30px;" startText="正在添加" id="adding" stopText="添加完成"/>
    </apex:outputPanel>
    
    <apex:outputPanel >
        <apex:actionStatus startStyle="font-size:40px;color:red;" stopStyle="font-size:30px;" startText="正在刪除" id="deleting" stopText="刪除完成"/>
    </apex:outputPanel>
      
    </apex:pageBlockSection>
    <apex:pageBlockSection title="功能區">
      <input type="button" onclick="OpenDialog()" id="addUser" value="選擇微信用戶(按鈕)"/>
      <apex:outputPanel id="AjaxBlock">
        <apex:variable value="{!0}" var="rowNum"/>
        <apex:pageBlockTable value="{!wechatuserList}" var="wu">
          <apex:column headerValue="序號">
            <apex:outputText value="{0}">
              <apex:param value="{!rowNum+1}"/>
            </apex:outputText>
          </apex:column>

          <apex:column headerValue="操作">
            <apex:commandLink value="刪除" action="{!deleteRow}" reRender="AjaxBlock" status="deleting" style="color:blue">
              <apex:param name="rowIndex" value="{!rowNum}"/>
            </apex:commandLink>

          </apex:column>
          <apex:column headerValue="昵稱">
            <apex:outputField value="{!wu.Name}"/>
          </apex:column>

          <apex:column headerValue="微信號">
          <apex:variable var="rowNum" value="{!rowNum+1}"/>
            <apex:outputField value="{!wu.openid__c}"/>
          </apex:column>

          <apex:column headerValue="是否有效">
            <apex:outputField value="{!wu.validornot__c}"/>
          </apex:column>

        </apex:pageBlockTable>
      </apex:outputPanel>
    </apex:pageBlockSection>
  </apex:pageBlock>
  <apex:actionfunction reRender="AjaxBlock" status="adding" immediate="true" action="{!GetChoose}" name="GetChoose" >
      <apex:param name="ChooseParam" assignTo="{!Choose}" value=""/>
  </apex:actionfunction>

  <div id="SelectWechatUser" style="height:470px;overflow-Y:auto;">
    <apex:outputPanel >
      <input type="button" value="確認選擇" onclick="ComfirmChoost()" class="btn"/>
    </apex:outputPanel>
    <apex:pageBlock >
      <apex:variable value="{!0}" var="rowNum2"/>
      <apex:pageBlockTable value="{!GetUserList}" var="glist">
        <apex:column headerValue="選擇" style="width:5%">
          <input type="checkBox" value="{!glist.Id}" name="checkedPro"/>
        </apex:column>
        <apex:column headerValue="序號" style="width:5%;text-align:center;">
          <apex:outputText value="{0}" >
            <apex:param value="{!rowNum2+1}"/>
          </apex:outputText>
        </apex:column>

        <apex:column headerValue="昵稱" style="width:30%">
          <apex:outputField value="{!glist.Name}" style="width:100%"/>
        </apex:column>

        <apex:column headerValue="微信號" style="width:30%">
          <apex:outputField value="{!glist.openid__c}" style="width:100%"/>
          <apex:variable var="rowNum2" value="{!rowNum2+1}"/>
        </apex:column>

        <apex:column headerValue="是否有效" style="width:30%">
          <apex:outputField value="{!glist.validornot__c}" style="width:100%"/>
        </apex:column>
      </apex:pageBlockTable>
    </apex:pageBlock>
  </div>
</apex:form>

  <script>
    var dialog;
    $(function () {
      dialog=jQuery("#SelectWechatUser").dialog({
                      autoOpen: false,
                      height:550,
                      width: 900,
                      modal: true
                });
    });
    function OpenDialog()
    {
      jQuery("#SelectWechatUser").dialog("open");
    }
    function ComfirmChoost()
    {
      var choose=[];
      var allPro=document.getElementsByName("checkedPro");
      for(var i=0;i<allPro.length;i++)
      {
        if(allPro[i].checked)
        {
          choose.push(allPro[i].value);
        }
      }
      if(choose.length==0)
      {
        alert("請選擇微信用戶");
        return;
      }
      else
      {
         jQuery("#SelectWechatUser").dialog("close");
         GetChoose(choose.join(';'));
      }
    }
  </script>
</apex:page>

然后下面是控制器的代碼:

public class SendMessageController {

    public List<wechatuser__c> GetUserList { get; set; }
    public String Choose{get;set;}
    public List<String> chooseIds{get;set;}
    public List<wechatuser__c> wechatuserList { get; set; }
    public SendMessageController()
    {
        wechatuserList=new List<wechatuser__c>();
        GetUserList=[select id,Name,openid__c,validornot__c from wechatuser__c];
    }


    public void GetChoose(){                              
        if(Choose !=null ){
            chooseIds = Choose.split(';');
            System.Debug('長度:'+wechatuserList.size());
            for(wechatuser__c model : [select id,Name,openid__c,validornot__c from wechatuser__c WHERE id IN :chooseIds]){             
                
                wechatuserList.add(model);                                            
            }
            System.Debug('長度:'+wechatuserList.size());
        }
    }
    public void deleteRow() {
        Integer rowIndex;
        rowIndex = Integer.valueOf(ApexPages.currentPage().getParameters().get('rowIndex'));
        wechatuserList.remove(rowIndex);
    }
}

大概效果圖就如下:

image

大致描述下這個頁面和控制器做了什么,首先點擊選擇微信用戶,然后出現一個dialog選擇框(jQuery ui風格),選上對應的微信用戶后,便會在上圖右下角出現對應的選擇,點擊刪除操作,便會刪除掉對應行,在向控制器get數據和post請求的時候(Ajax),請求的時候在請求提示區會有對應的正在請求數據的提示。整個過程都是AJAX,卻完全不是用js做到的,相當方便,當然也支持通過js去完成,最后也大致說明下。

image

當點擊選擇微信號按鈕出現一個dialog,這個就不多講,直接js打開,只不過前面需要引用jquery ui的js和css

dialog的代碼是這樣構成的。

<div id="SelectWechatUser" style="height:470px;overflow-Y:auto;">
    <apex:outputPanel >
      <input type="button" value="確認選擇" onclick="ComfirmChoost()" class="btn"/>
    </apex:outputPanel>
    <apex:pageBlock >
      <apex:variable value="{!0}" var="rowNum2"/>
      <apex:pageBlockTable value="{!GetUserList}" var="glist">
        <apex:column headerValue="選擇" style="width:5%">
          <input type="checkBox" value="{!glist.Id}" name="checkedPro"/>
        </apex:column>
        <apex:column headerValue="序號" style="width:5%;text-align:center;">
          <apex:outputText value="{0}" >
            <apex:param value="{!rowNum2+1}"/>
          </apex:outputText>
        </apex:column>

        <apex:column headerValue="昵稱" style="width:30%">
          <apex:outputField value="{!glist.Name}" style="width:100%"/>
        </apex:column>

        <apex:column headerValue="微信號" style="width:30%">
          <apex:outputField value="{!glist.openid__c}" style="width:100%"/>
          <apex:variable var="rowNum2" value="{!rowNum2+1}"/>
        </apex:column>

        <apex:column headerValue="是否有效" style="width:30%">
          <apex:outputField value="{!glist.validornot__c}" style="width:100%"/>
        </apex:column>
      </apex:pageBlockTable>
    </apex:pageBlock>
  </div>

apex中是通過上面這樣的寫法進行數據填充的,其中<apex:pageBlockTable value="{!GetUserList}" var="glist">   value中的值便是對應到控制器中的GetUserList,這個變量類型是List<wechatuser__c>,所以當頁面加載完的時候,如果GetUserList有值的話,便會循環填充滿pageBlockTable了,控制器在構造函數中便已經查了數據庫,並賦值在這個變量中,另外<apex:variable value="{!0}" var="rowNum2"/>這個我個人理解是一個會根據pageBlockTable中記錄條數,進行遞增的一個變量,這里我就用來給每條記錄一個序號,刪除對應的行也是通過這個變量去取得rowIndex來操作的。另一個pageBlockTable的原理也是一樣的。

      在打開的dialog對話框選擇了對應的條目后,js便把選擇了的id傳到控制器,使用的是actionfunction

<apex:actionfunction reRender="AjaxBlock" status="adding" immediate="true" action="{!GetChoose}" name="GetChoose" >
      <apex:param name="ChooseParam" assignTo="{!Choose}" value=""/>
  </apex:actionfunction>

在actionfunction中可以定義apex: param 參數傳遞過去,而assignTo這個attribute則是對應到了控制器里面的Choose變量,變量有get和set方法,這樣,當調用GetChoose(choose.join(';')) 便把想傳遞的參數直接到了控制器里面的Choose去,這里是我個人覺得挺有趣的。緊接着便是調用數據庫把對應記錄查出來,然后wechatuserList.add(model); 這樣視圖這邊便會刷新AjaxBlock中的數據,這里就要注意了,如果你覺得僅僅更新wechatuserList便會讓視圖綁定了這個變量的table也進行刷新的話,你就錯了,沒有進行過處理的話,是會刷新整個頁面,那么頁面是新的,數據也就是新的了,剛才傳過去的id數據也對應丟失,這樣當然不是我們想要的。

     在ajax請求的過程中,如果實現 1.讓用戶知道正在請求數據,頁面不刷新  2.請求完后,僅僅刷新想要刷新的部分呢。 第一個問題:在actionfunction中不是有一個status屬性嗎,注意看 它對應的是

<apex:outputPanel >
        <apex:actionStatus startStyle="font-size:40px;color:red;" stopStyle="font-size:30px;" startText="正在添加" id="adding" stopText="添加完成"/>
    </apex:outputPanel>

看屬性也就很明顯,在Ajax請求過程中status屬性是用來通知用戶瀏覽器正在請求某個操作(如果網絡卡的話,不卡當然這個信息也不會看到),startText和stopText的值便是通過改變對應的值來告知ajax請求的過程和完成的狀態。問題二:對於actionfunction中的reRender屬性,便是指定需要ajax刷新的區域,類似這個例子,考慮ajax請求完成后,更新了wechatuserList的值,而視圖中的pageBlockTable剛好綁定了這個變量,如此,ajax請求完后,我們希望刷新這個pageBlockTable來顯示最新的狀態,於是我用一個div或者ouputPanel來包住這個table,然后賦值一個id,再把這個id給到actionfunction的attribute  reRender。這樣,在actionfunction執行完后,便會刷新對應的區域,實現了Ajax的請求。

     一樣的道理,點擊commandLink 帶上了apex: param 參數,帶上需要刪除的行rowIndex,在點擊了刪除按鈕后,也是刪除List<wechatuser__c>的值,然后ajax刷新AjaxBlock。

     總結一下,當視圖需要訪問控制器的某個方法或者變量(變量需要get和set),只需要{!函數名(或者變量名)}  這樣便可以訪問控制器,如果需要帶上參數便在標簽中帶上<apex: param>  可以通過綁定控制器的變量和視圖中的pageblocktable來實現數據的同步,如果改變了對應的值,刷新視圖對應的部分便可以。當然除了這樣的方法實現控制器和視圖的通訊和Ajax請求,我們也可以通過js來完成,下面代碼便是在js中調用控制器的函數,並在回調函數中進行對應的處理。

SendMessageController.AutoAjax(
                           Param,
                           function(result, event){
                               if (event.status) {
                                     //這里是請求完成處理的事情
                                  }
                               //這里是當請求狀態不正常(錯誤或者網絡延遲),處理區域
                            },
                            {escape: true}//這個是html編碼的轉義開關,之前的一篇博客有講過
                        );

js方法中SendMessageController便是控制器名,.后面的便是對應的方法名,控制器的方法前需要帶上@RemoteAction標簽,函數第一個便是傳過去的參數,如果有多個參數,用逗號隔開便可以,有function的便是回調函數,最后那個是html轉義的標志,前面有講到,大概的控制器和視圖交互就是這樣,應該還不全,也是研究了一個星期的成果而已,后面再慢慢完善吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM