2014-10-08 22 views
0

選擇在我的MVC5控制,我填兩份名單在我的ViewModel像這樣:隱藏一個控制和顯示了另一個當用戶在MVC5和EF6

public async Task<ActionResult> Create() 
     { 
      var db = new ApplicationDbContext(); 
      var model = new RegisterViewModel() 
      {      
       RegionsList = db.Regions.ToList().Select(x => new SelectListItem() 
       { 
        Selected = false, 
        Text = x.Name, 
        Value = x.Name 
       }), 
       CompanyList = db.Companies.ToList().Select(x => new SelectListItem() 
       { 
        Selected = false, 
        Text = x.Name, 
        Value = x.CompanyId.ToString() 
       }) 
      }; 
      return View(model); 
     } 

然後,在我看來,我展示公司作爲一個DropDownList和地區爲一組的複選框:

<div class="form-group"> 
      @Html.LabelFor(model => model.CompanyList, new { @class = "control-label col-md-2" }) 
      <div class="col-md-10"> 
       @Html.DropDownListFor(c => c.SelectedCompanyId, Model.CompanyList, new { @class = "form-control" }) 
      </div> 
     </div> 
    <div class="form-group"> 
     @Html.Label("Assign the user to one or more regions", new { @class = "control-label col-md-2" }) 
      <span class=" col-md-10"> 
       @foreach (var item in Model.RegionsList) 
       { 
        <input type="checkbox" name="SelectedRegionNames" value="@item.Value" checked="@item.Selected" class="checkbox-inline" /> 
        @Html.Label(item.Value, new { @class = "control-label" }) 
       } 
      </span> 
     </div> 

該工程確定,但它是一個有點亂,因爲顯示所有公司的所有區域。我想隱藏一組複選框,直到選中一個公司,然後隱藏公司下拉列表並顯示region.CompanyId ==所選的區域列表。

任何人都可以教我如何做到這一點嗎?

+1

如果你只是在瀏覽器中顯示/隱藏UI的一部分,那麼我會建議使用JavaScript來代替服務器端代碼。基本上,現在將所有內容都渲染到頁面上,並將其設置爲默認情況下不可見。當用戶與頁面元素交互時,顯示應該顯示的元素。 – David 2014-10-08 18:37:21

+0

我不認爲我只是顯示/隱藏,因爲RegionList的內容需要根據從CompanyList中選擇的內容進行更改。 – davecove 2014-10-08 19:25:37

+0

它會發回服務器並重新呈現頁面嗎?如果是這樣的話,我想你的視圖可以綁定到模型上的過濾列表,而不是整個列表。如果過濾器標準在模型上可用,那麼可能只是創建基於這些標準過濾列表的只讀屬性? – David 2014-10-08 19:27:03

回答

3

如果你想要做的過濾服務器端,那麼你的操作順序可能是這個樣子:

  • 顯示所有公司,但沒有地區
  • 應對變化的事件,爲企業形成元素
  • 獲取來自AJAX相關的區域叫
  • 創建區域選擇

在第一步中,你所做的就是不再顯示任何區域。所以,你不需要他們在視圖模型:

var model = new RegisterViewModel() 
{      
    CompanyList = db.Companies.ToList().Select(x => new SelectListItem() 
    { 
     Selected = false, 
     Text = x.Name, 
     Value = x.CompanyId.ToString() 
    }) 
}; 
return View(model); 

但你需要一種方法來確定其中將包含這些客戶端的HTML元素。一個id值很好地工作:

<span id="regionsSelection" class="col-md-10"></span> 

在第二個步驟,你一個change處理程序附加到具有公司select元素。當然,您需要一種方法來識別該元素。舉例來說,如果它的name屬性SelectedCompanyId那麼這應該工作:

$('select[name="SelectedCompanyId"]').change(function() { 

}); 

第三步將涉及使該change處理器內的AJAX調用。但在我們做到這一點之前,我們需要一個服務器端控制器操作來獲取基於選定公司的區域。我主要猜對你的對象模型的細節,但結構會是這樣的:

public ActionResult GetRegions(int companyId) 
{ 
    var db = new ApplicationDbContext(); 
    var regions = db.Regions.Where(r => r.Companies.Any(c => c.Id == companyId)); 
    return Json(regions); 
} 

的思路是獲取與所提供的公司ID相關聯的區域,並返回它們作爲一個JSON數組。然後,您可以從change處理程序中的客戶端代碼中調用該操作。事情是這樣的:

那(或非常相似,它的東西)應該從服務器獲取的區域。 (請注意,我在這裏使用了一些服務器端代碼來定義URL)。

第四步然後發生在那個用於AJAX調用的done處理程序中,其中您使用響應中的數據創建你的HTML元素。再次,我將主要猜測你的對象的結構。您可能需要在瀏覽器的調試工具中手動檢查實際的JSON響應,以確保它符合您的期望。

如果response成功是區域的集合,然後使用它可能是這個樣子:

$('#regionSelection').html(''); 
for (var i = 0; i < response.length; i++) { 
    $('#regionSelection').append('<input type="checkbox" name="SelectedRegionNames" value="' + response[i].Name + '" checked="false" class="checkbox-inline" />'); 
    $('#regionSelection').append('<label class="control-label">' + response[i].Name + '</label>'); 
} 

正如你所看到的,第一我空無論是當前內容的span(刪除任何區域然後我所做的就是手動添加HTML元素到span,問題代碼在初始頁面渲染過程中將其附加到它們後面

我不能100%保證這是您的複製/粘貼解決方案需求,因爲我不知道你的模型結構或你的用戶體驗或用例。但就動態獲取服務器中的對象列表來驅動客戶端用戶界面而言,這可以解決問題。

+0

純金!突破的額外點進入功能步驟,並解釋每一個代碼。超級工作! – davecove 2014-10-09 19:41:40

+0

@davecove:謝謝,很高興我能幫到你! – David 2014-10-09 19:45:21

+0

我在公司列表中添加了一個通用'選擇一個...'條目。如果此頁面被重新渲染,如果控制器檢測到不可接受的用戶輸入,我如何檢測公司列表中是否選擇了「選擇一個...」之外的選項?我需要這樣做,因此我可以將所選公司的複選框放在頁面上。不是什麼要掛鉤。 – davecove 2014-10-09 20:30:12

0

你有兩個選擇:在服務器上

  1. 過濾器(發送形式倒流,回到了正確的項目)

    • 用戶可以複製網址並分享通過電子郵件過濾視圖-Mail
    • 您的網站的響應速度較慢。回傳需要時間,特別是在移動連接
    • 適合大量的選擇,客戶
  2. 過濾器上(發送一切首次顯示/隱藏項目)

    • 的網址保持不變(如果你沒有做一些特別的東西)
    • 更快的響應時間
    • 適合的選項中小量

替代一個可以用適當的視圖模型來完成:

public class FilteredRegions 
{ 
    public FilteredRegions() 
    { 
     Regions = new List<Region>(); 
    } 

    public int SelectedCompanyID { get; set; } 
    public IEnumerable<SelectListItem> CompanyList { get; set; } 

    public int SelectedRegionID { get; set; }  
    public virtual ICollection<Topic> Regions { get; set; } 
} 

替代兩(這我倒是建議的基礎上,你有低於1000個區域的假設)

把每個區域中的觀點,用一個漂亮的數據屬性就可以了:

<div class="form-group"> 
@Html.Label("Assign the user to one or more regions", new { @class = "control-label col-md-2" }) 
    <span class=" col-md-10"> 
     @foreach (var item in Model.RegionsList) 
     { 
      <input type="checkbox" name="SelectedRegionNames" value="@item.Value" checked="@item.Selected" class="checkbox-inline hide" data-company="@item.CompanyId" /> 
      @Html.Label(item.Value, new { @class = "control-label" }) 
     } 
    </span> 
</div> 

而不是附加一個事件句柄下拉菜單中,做這樣的事情:(未測試)

$('#dropdown').change(function() { 
    var companyID = $(this).value; 
    $('input[data-company]').hide(); 
    $('input[data-company="' + companyID + '"]').show(); 
}) 

即當公司選擇的變化,隱藏所有的複選框,顯示的是正確的。 你需要jQuery的片段。

+0

我喜歡這裏的概念:但是當我添加'data-company =「@ item.CompanyId位:'System.Web.Mvc.SelectListItem'不包含'CompanyId'的定義時,我得到這個錯誤。 SelectListItem將CompanyId包含爲SelectListItemWithComapnyId,但DropDownListFor不知道使用它,因此它看不到我的添加。此外,腳本如何知道要更改哪個控件? – davecove 2014-10-09 02:57:23

相關問題