4

Я пытаюсь узнать больше о MVC 5, поэтому я пишу блог-сайт для себя, чтобы больше узнать, как я иду.Добавить элементы для выбора списка на стороне клиента в MVC 5 ASP

Я создал список избранных тегов и хотел бы иметь возможность добавлять новые теги из страницы создания блога, вместо того, чтобы забывать устанавливать теги перед созданием нового сообщения. Я думаю о строках кнопки «Добавить тег», которая отображает окно модального окна, где пользователь может добавить новый тег.

Вот мой контроллер действия:

public ViewResult CreateBlogPost() 
{ 
    CreateEditBlogViewModel viewModel = new CreateEditBlogViewModel(); 
    viewModel.BlogPost = new Core.BlogPost(); 

    viewModel.BlogPost.ShortBody = "<p>Something short and sweet to describe the post</p>"; 
    viewModel.BlogPost.Body = "<p>Enter something blog worthy here...</p>"; 

    viewModel.Tags = new SelectList(_blogRepo.BlogTags(), "Id", "Name"); 
    viewModel.Categories = new SelectList(_blogRepo.BlogCategories(), "Id", "Name"); 

    return View(viewModel); 
} 

А вот HTML в представлении:

<div class="row"> 
    <div class="form-group"> 
     @Html.LabelFor(m => m.BlogPost.Tags, new { @class = "col-md-2 control-label" }) 
     <div class="col-md-10"> 
     @Html.ListBoxFor(m => m.SelectedTags, Model.Tags, new { @class = "form-control chosen-select", @data_placeholder = "Start typing to see a list of tags" }) 
     </div> 
    </div> 
</div> 

<div class="row"> 
    <!-- Button trigger modal --> 
    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#tagModal"> 
      Add Tag 
    </button> 
</div> 

Вот мой частичный вид в модальном окне:

@using (Html.BeginForm("SaveTag", "Home", FormMethod.Post, new { id = "tag-form" })) 
{ 
    @Html.AntiForgeryToken() 

    <!-- Modal --> 
    <div class="modal fade" id="tagModal" tabindex="-1" role="dialog" aria-labelledby="tagModalLabel"> 
     <div class="modal-dialog" role="document"> 
      <div class="modal-content"> 
       <div class="modal-header"> 
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> 
        <h4 class="modal-title" id="tagModalLabel">Enter a name for a new tag</h4> 
       </div> 
       <div class="modal-body"> 
        <input type="text" id="Name" placeholder="Enter a new tag name" /> 
       </div> 
       <div class="modal-footer"> 
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> 
        <button type="submit" class="btn btn-primary">Save changes</button> 
       </div> 
      </div> 
     </div> 
    </div> 

} 

Можно ли добавить тег на стороне клиента, сохранить его в db, а затем добавить его в мои теги, выбрать список wit hout обновить страницу?

PS: FYI Я использую Выбранный мультивыбор от here.

@section scripts { 
    <script type="text/javascript" src="~/Scripts/chosen.jquery.min.js"></script> 
    <script type="text/javascript"> 
     $(".chosen-select").chosen() 
    </script> 
} 

EDIT: Я обновил этот вопрос со всеми код, который делает вид дает пользователю модальное окно, чтобы ввести новое имя тега. Я просто не уверен, как отправлять сообщения, не переходя от страницы, поэтому я предполагаю, что требуется какая-то должность Ajax. И затем, что делать с данными, которые возвращаются с этой должности. Как добавить новую сохраненную запись в список выбора?

Я знаю, что тег не переходит к методу контроллера, так как он не привязан к какой-либо модели, но, поскольку я использую модель представления на родительском представлении, я не уверен, как бы я справился с этим здесь тоже.

ответ

1

Для того, чтобы динамически добавлять новую BlogTag в представлении вам нужно будет разместить новый тег Name с помощью Ajax, к способу контроллера, который экономит BlogTag и возвращает его новое значение ID.Ваш метод контроллера будет что-то вроде

[HttpPost] 
public JsonResult CreateTag(string name) 
{ 
    BlogTag tag = new BlogTag(){ Name = name }; 
    db.BlogTags.Add(tag); 
    db.SaveChanges(); 
    return Json(tag.ID); 
    // If the above code could result in an error/exception, catch it and return 
    // return Json(null); 
} 

Тогда в представлении, обрабатывать диалоги кнопку отправить, чтобы отправить значение и обновить список тегов

var url = '@Url.Action("CreateTag")'; 
var tagList = $('#SelectedTags'); 
$('#tag-form').submit(function() { 
    var tagName = $('#Name').val(); 
    $.post(url, { name: tagName }, function(id) { 
    if (id) { 
     // add the new tag to the list box 
     tagList.append($('<option></option>').val(id).text($('#Name').val())); 
     // trigger the chosen update 
     tagList.trigger("chosen:updated"); 
    } else { 
     // Oops - display an error message? 
    } 
    }).fail(function (result) { 
    // Oops - display an error message? 
    }); 
    return false; // cancel the default submit 
}); 

Примечание стороны: я рекомендовал бы создать view model for BlogTagVM (содержит свойство для Name с атрибутами проверки) и связанное с ним частичное представление (скажем _AddBlogTag.cshtml), которое генерирует диалог html, так что в главном представлении вы можете использовать @Html.Partial("_AddBlogTag", new BlogTagVM()), который позволит вам использовать строго типизированный html помощников, и включить проверка на стороне клиента.

Обратите внимание, что вложенные элементы <form> недействительны html, поэтому убедитесь, что html для диалога находится за пределами основного тега <form> для представления.

+0

Я вижу, как это работает и реализуется. Я вижу, что новая опция добавляется в список опций в источнике html с помощью инструментов разработчика Firefox (похоже, я был ближе к решению, чем я думал). Однако выбранный элемент select ui, похоже, не распознает его до обновления страницы. Итак, чтобы уточнить - он добавляет источник html '

+0

Отмените это, я прочитал выбранный веб-сайт и есть событие изменения/обновления, которое вы можете вызвать, который является' $ («#SelectedTags»). Trigger («selected: updated»); 'after' tagList.append ($ ('') .val (ID) .text (tagName.val()));' Если вы могли бы разработать о том, как я буду справляться с неспособностью сохранить тег в db, я тоже с радостью добавлю +1! Приветствия. – paulpitchford

+0

У меня уже была строка 'tagList.trigger (" selected: updated ");' в моем ответе :). Существует несколько способов обработки отказа: вы можете «вернуть Json (null)» и в скрипте проверить 'if (id) {// добавить опцию} else {// oops}' или вы можете вернуть 'HttpStatusCodeResult', указывающий ошибку, а затем добавить '.fail (function (result) {// oops});' to '$ .post' - я обновил ответ на примере –

0

Я делаю что-то подобное, я думаю, это может помочь. В моем случае я «перемещаю» значения из одного списка в другой (от «доступного» до «используемого»), а затем сохраняя значения «используемого» списка. В любом случае, в контроллере «использованный» список отображается как массив строк. Вот мой код:

 public ActionResult PinchHit(FormCollection form, LineupViewModel lvm, String[] UsedPlayers) 
     { 
[Snip] 
      if (ModelState.IsValid && lineupResults.IsValid) 
      { 
[Snip] 
       foreach (String usedID in UsedPlayers) 
       { 
        gameState.HomeUsedPlayersIDs.Add(Convert.ToInt32(usedID)); 
       } 
       uow.Repository<GameState>().Update(gameState); 
       uow.SaveChanges(); 
       return RedirectToAction("Index", "GameSummary"); 
      } 
[Snip] 
      return View(lvm2); 
     } 

Надеюсь, что это поможет.

За мой комментарий:

Вот механизм обратного вызова AJAX я использовал для извлечения данных из базы данных без перезагрузки страницы, вы можете использовать его, чтобы сохранить данные в базу данных вместо.

<script type="text/javascript"> 
     function getPositions(id, control) { 
      $.ajax({ 
       url: "@Url.Action("GetPositions", "Lineup")", 
       data: 
       { 
        id: id 
       }, 
       dataType: "json", 
       type: "POST", 
       error: function() { 
        alert("An error occurred."); 
       }, 
       success: function (data) { 
        $(control).html(""); 
        $.each(data, function (i, item) { 
         $(control).append("<option value=\"" + item.Value + "\">" + item.Text + "</option>"); 
        } 
        ); 
       } 
      }); 
     } 
</script> 

затем в контроллере:

[HttpPost] 
    public ActionResult GetPositions(int id) 
    { 
     Player player = uow.Repository<Player>().GetById(id); 
     if (player == null) 
     { 
      return (null); 
     } 
     List<SelectListItem> positionList = new SelectList(player.Positions, "ID", "ShortName").ToList(); 
     return Json(positionList); 
    } 

Довольно стандартный материал действительно.

+0

Спасибо, но я думаю, что это приведет к загрузке страницы, правильно? Я стараюсь избегать этого, если это возможно. Я знаю, что могу опубликовать форму и перезагрузить представление с предварительно введенными полями и обновить список выбора, но я надеюсь сделать это на стороне клиента. – paulpitchford

+0

Что я делаю, это сбор всех значений на стороне клиента, а затем их сохранение во время публикации (когда пользователь выполнил все изменения и нажал кнопку отправки.) Вы просите, чтобы изменения сохранялись каждый раз, когда они добавляются тег без перезагрузки страницы? В этом случае вам понадобится обратный вызов AJAX для метода JSON. Я отредактирую свой ответ. – Duston

+0

Спасибо, но, как полный новичок, особенно с JS, мне не хватает информации, чтобы доставить меня туда, где мне нужно. У меня есть модальное окно с формой, которая открывается, но мои данные формы не передаются моему контроллеру, и я не уверен, как обращаться с новым тегом, как только он будет сохранен. (Я думал, что раньше был ближе, чем на самом деле!) – paulpitchford