locked
Set a value in a view model if user clicks a button and hide an element RRS feed

  • Question

  • User1185448985 posted

    i would appreciate some help figuring out how to set a value in a model via javascript from the view,

    I want to set isDeleted property to true if the user clicks on the button of delete in one of SentencesLists[], then hide that row from the table and deal with the sentence in the action.

    i would like to set the proberty in the model it self via javascript so when i get the model result in action i get the sentences that are clicked to delete.

    Any recomendations?

    EditStoryViewModel

        public class EditStoryViewModel
        {
            public IEnumerable<Childs> ChildrenList { get; set; }
            public Childs Child { get; set; }
            public Story Story { get; set; }
            public IList<SentenceViewModel> SentencesLists { get; set; }
    
        }

    SentenceViewModel

        public class SentenceViewModel
        {
                public int Id { get; set; }
                public string SentenceText { get; set; }
                public string SequenceNo { get; set; }
                public bool isDeleted { get; set; } // WHAT I NEED TO SET TO TRUE IF USER CLICKS VIA JAVASCRIPT
                public Image Image { get; set; }
                public IFormFile ImageFile { get; set; }
                public IFormFile AudioFile { get; set; }
        }

    My View

    @model TestApplication.Models.ViewModels.EditStoryViewModel
    ................................ Lines of code ...................................
    <tbody id="heree">
                                                @for (int i = 0; i < Model.SentencesLists.Count; i++)
                                                {
    
                                                    <partial name="_SentenceEditor" for="@Model.SentencesLists[i]" />
                                                }
    
                                            </tbody>
                                            <tfoot>
                                                <tr>
                                                    <td colspan="5" style="text-align: left;">
                                                        <a id="addItem" asp-action="BlankSentence" asp-controller="Story" class="btn btn-primary btn-lg btn-block ">Add Sentence</a> <br />
                                                    </td>
                                                </tr>
                                            </tfoot>
    ................................ Lines of code ...................................
    @section Scripts
    {
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
    
        <script type="text/javascript">
           
            $("#addItem").click(function () {
                $.ajax({
                    url: this.href,
                    cache: false,
                    success: function (html) { $("#heree").append(html); }
                });
                return false;
            });
    
    
        </script>
    
    }

    PartialView

    @model TestApplication.Models.ViewModels.SentenceViewModel
    @using HtmlHelpers.BeginCollectionItemCore;
    @{
        ViewData["Title"] = "_SentenceEditor";
    }
    
    <tr id="editorRow">
        @using (Html.BeginCollectionItem("SentencesLists"))
        {
            <td class="col-md-4"><input asp-for="@Model.SentenceText" type="text" class="form-control"></td>
            <td class="text-center col-md-2">
                @if (Model.Image != null)
                {<img src="@Model.Image.ImageSelected" /> <input asp-for="@Model.Image.ImageSelected" type="text" hidden />}
                else
                {<h6>-</h6>}
            </td>
            <td class="col-md-2"><input asp-for="@Model.ImageFile" type="file" class="form-control-file border"></td>
            <td class="col-md-2"><input asp-for="@Model.AudioFile" type="file" class="form-control-file border" disabled></td>
            <td class="col-md-1"><input type="submit"  asp-controller="Story" asp-action="DeleteSentence" asp-route-id="@Model.Id" class="btn btn-md btn-danger ibtnDel" id="deleteRow" value="Delete" /></td>
            <td class="col-md-1"><input asp-for="@Model.Id" type="text" class="form-control" hidden></td>
        }
    </tr>
    
    
    @section Scripts {
    
        <script type="text/javascript">
    
    
        </script>
    }

    Action

            [HttpPost]
            public async Task<IActionResult> Edit(EditStoryViewModel model)

    Thanks in advance

    Monday, August 24, 2020 9:35 PM

Answers

  • User-17257777 posted

    Hi Amani Al,

    The button value will not be submitted when you submit the form. You can add a hidden input before the button.

    <td class="col-md-1">
        <input type="hidden" asp-for="@Model.isDeleted" />
        <input type="button" onclick="toDelete.call(this)" asp-for="@Model.isDeleted" class="btn btn-md btn-danger" />
    </td>

    Then change the value of the hidden input in toDelete function.

    function toDelete() {
        $(this).prev().attr('value','true');
        $(this).attr('value', 'true');
    }

    Result:

    Best Regards,

    Jiadong Meng

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, August 27, 2020 7:56 AM

All replies

  • User-17257777 posted

    Hi Amani Al,

    It is very simple, you can get the current sentence id when you click the submit button. Then send the id to DeleteSentence action via ajax to set the IsDeleted property as true. Also, the script should be written in main view.

    Here I test the code with a static list, in your case the data may come from database, after changing the property, you need to save it to database.

    Main View:

    @model EditStoryViewModel
    <table>
        <tbody id="heree">
            @for (int i = 0; i < Model.SentencesLists.Count; i++)
            {
                <partial name="_SentenceEditor1" for="@Model.SentencesLists[i]" />
            }
        </tbody>
        <tfoot>
            <tr>
                <td colspan="5" style="text-align: left;">
                    <a id="addItem" asp-action="BlankSentence" asp-controller="Story" class="btn btn-primary btn-lg btn-block ">Add Sentence</a> <br />
                </td>
            </tr>
        </tfoot>
    </table>
    @section Scripts
    {
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
    
        <script type="text/javascript">
    
            $("#addItem").click(function () {
                $.ajax({
                    url: this.href,
                    cache: false,
                    success: function (html) { $("#heree").append(html); }
                });
                return false;
            });
    
            $("[name=deleteRow]").on("click", function () {
                $(this).parents("tr.editorRow:first").remove();
                var id = $(this).attr("data-id");
                $.ajax({
                    method: 'post',
                    url: 'Story/DeleteSentence',
                    data: {
                        id: id
                    },
                    success: function () {
                        alert("Deleted");
                    }
                })
                return false;
            });
        </script>
    }
    

    Partial View:

    @model SentenceViewModel
    @{
        ViewData["Title"] = "_SentenceEditor";
    }
    
    <tr class="editorRow">
    
        <td class="col-md-4"><input asp-for="@Model.SentenceText" type="text" class="form-control"></td>    
        <td class="col-md-1"><input type="submit" name="deleteRow" asp-controller="Story" asp-action="DeleteSentence" data-id="@Model.Id" class="btn btn-md btn-danger ibtnDel" id="deleteRow" value="Delete" /></td>
        <td class="col-md-1"><input asp-for="@Model.Id" type="text" class="form-control" hidden></td>
    
    </tr>
    
    
    

    Controller:

    public static EditStoryViewModel editStoryViewModel = new EditStoryViewModel
    {
        SentencesLists = new List<SentenceViewModel>
        {
            new SentenceViewModel{ Id = 1, SentenceText = "AAA"},
            new SentenceViewModel{ Id = 2, SentenceText = "BBB"},
            new SentenceViewModel{ Id = 3, SentenceText = "CCC"},
        }
    };
    
    public IActionResult Index()
    {
        return View(editStoryViewModel);
    }
    
    [HttpPost]
    public void DeleteSentence(int id)
    {
        var sentence = editStoryViewModel.SentencesLists.Where(s => s.Id == id).FirstOrDefault();
        sentence.isDeleted = true;
    }

    Result:

    Best Regards,

    Jiadong Meng

    Tuesday, August 25, 2020 6:43 AM
  • Tuesday, August 25, 2020 6:46 AM
  • User1185448985 posted

    your solution is exactly what i need except that in my case i'm fetching SentencesLists from the database to the GET Edit Action which is not a public static list as in your example.  i want to set the isDeleted to true then update the model in the main view so when the user is done editing, the POST action handles the rest where we can see the what happened to the list ....

    Edit //GET

            public async Task<IActionResult> Edit(int? id){
                var sentenceListVM = new List<SentenceViewModel>();
                sentenceListVM.Add(...);
                sentenceListVM.Add(...);
                ...........
                modelVM = new EditStoryViewModel
                {
                    Child = new Childs(),
                    Story = story,
                    SentencesLists = sentenceListVM // declared and populated previously 
                };
                return View(modelVM);
    
          }

    thank you

    Wednesday, August 26, 2020 1:45 AM
  • User-17257777 posted

    Hi Amani Al,

    Amani Al

    your solution is exactly what i need except that in my case i'm fetching SentencesLists from the database to the GET Edit Action which is not a public static list as in your example.  i want to set the isDeleted to true then update the model in the main view so when the user is done editing, the POST action handles the rest where we can see the what happened to the list ....

    Yeah, you can update the isDelete property in the delete method, and save the changes in database. Then in edit get method fetch the sentenceslists from database, return the updated viewmodel to the view, so you can populate  the view with the newest data.

    Have you solved the problem, is there any other questions?

    Best Regards,

    Jiadong Meng

    Wednesday, August 26, 2020 7:45 AM
  • User1185448985 posted

    you are correct but isDeleted is a property in SentenceViewModel not in database therefore no such property is saved in DB. I want to update the value in my model only.

    i've tried a new way to change the value via javascript and it was unsuccessful.

    if any one can help if i'm missing something

    modified partial view

    @model TestApplication.Models.ViewModels.SentenceViewModel
    @using HtmlHelpers.BeginCollectionItemCore;
    @{
        ViewData["Title"] = "_SentenceEditor";
    }
    
    <tr id="editorRow">
        @using (Html.BeginCollectionItem("SentencesLists"))
        {
            <td class="col-md-4"><input asp-for="@Model.SentenceText" type="text" class="form-control"></td>
            <td class="text-center col-md-2">
                @if (Model.Image != null)
                {<img src="@Model.Image.ImageSelected" /> <input asp-for="@Model.Image.ImageSelected" type="text" hidden />}
                else
                {<h6>-</h6>}
            </td>
            <td class="col-md-2"><input asp-for="@Model.ImageFile" type="file" class="form-control-file border"></td>
            <td class="col-md-2"><input asp-for="@Model.AudioFile" type="file" class="form-control-file border" disabled></td>
            <td class="col-md-1"><input type="button" onclick="toDelete.call(this)" asp-for="@Model.isDeleted" class="btn btn-md btn-danger" /></td>
            <td class="col-md-1"><input asp-for="@Model.Id" type="text" class="form-control" hidden></td>
        }
    </tr>
    
    
    @section Scripts {
    
        <script type="text/javascript">
    
    
        </script>
    }
    

    main view

    <script type="text/javascript">
           
            $("#addItem").click(function () {
                $.ajax({
                    url: this.href,
                    cache: false,
                    success: function (html) { $("#heree").append(html); }
                });
                return false;
            });
    
    function toDelete() {
    
                $(this).attr('value', 'true');
    
            }
    
    
    </script>

    output:

    i've tried to add a GIF as i've seen in posts and this is the best i can do for now :))

    https://imgur.com/a/l1VZBCY

    Thursday, August 27, 2020 2:57 AM
  • User-17257777 posted

    Hi Amani Al,

    The button value will not be submitted when you submit the form. You can add a hidden input before the button.

    <td class="col-md-1">
        <input type="hidden" asp-for="@Model.isDeleted" />
        <input type="button" onclick="toDelete.call(this)" asp-for="@Model.isDeleted" class="btn btn-md btn-danger" />
    </td>

    Then change the value of the hidden input in toDelete function.

    function toDelete() {
        $(this).prev().attr('value','true');
        $(this).attr('value', 'true');
    }

    Result:

    Best Regards,

    Jiadong Meng

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, August 27, 2020 7:56 AM
  • User1185448985 posted

    You've solved the problem perfectly!!!!!!.

    i can't stop looking at the result .. thanks a lot .. i appreciate your time and effort

    you are the best

    Friday, August 28, 2020 1:38 AM