Search code examples
c#formsasp.net-coreeditrazor-pages

How to assign property in PageModel (by button) for form, maintaining selected page layout [ASP.NET/Razor Page]


My project has page to manage armors. So far page allows user to show table from DB, create new armor and delete. Unfortunately, I was unable to implement editing/updating.
When user first open page what is seen is table with items and each item have 2 buttons (edit and delete). Above table lays button making DIV containing table disappear and showing DIV containing form. Edit button does this same. This is handled by JavaScript.
I want to use this same form to update armors. But to do it, first need to assign selected armor to Armor property in PageModel. So far, I was able to do it with IActionResult OnPost method, but page then is reloaded losing all my effort. When I tried to return Page() then my page was reloaded with empty table, if I use RedirectToPage(“PageName”) then I still lose selected item and by default table is shown, not the form with selected armor data. How can I do it? It is possible without using additional JavaScript but OnPost metod/s? If not, what can I change and how?
I am using asp.net core 3.1, Entity Framework and Razor Pages.
GitHub: https://github.com/Mlorism/LastTemple/tree/master/LastTemple/Pages/Manage

CSHTML:

<div class="col-7 pl-5 pr-5">
    <div id="armourTable" class="text-center">
        <button class="btn btn-outline-light mb-2" onclick="ToggleColumn(1)">Stwórz pancerz</button>
        <table class="table text-light text-center">
            <thead>
                <tr>
                    <th scope="col">Id</th>
                    <th scope="col">Nazwa</th>
                    <th scope="col">Odp. fiz.</th>
                    <th scope="col">Odp. mag.</th>
                    <th scope="col"></th>                     
                    <th scope="col"></th>
                </tr>
            </thead>
            <tbody>
                @foreach (var item in Model.Armors)
                {
                    <tr id="[email protected]">
                        <th scope="row">@item.Id</th>                 
                        <td>@item.Name</td>
                        <td>@item.DamageResistance</td>
                        <td>@item.MagicResistance</td>
                        <td><form method="post"><button class="btn btn-outline-warning" type="submit" onclick="Edit(@item.Id)" asp-page-handler="LoadArmor" asp-route-id="@item.Id">Edytuj</button></form></td>
                        <td><form method="post"><button class="btn btn-outline-warning" type="submit" asp-page-handler="Delete" asp-route-id="@item.Id">Usuń</button></form></td>
                    </tr>
                }
            </tbody>
        </table>
    </div>

    <div id="armourForm" class="p-5">
        <form id="manipulateArmor" method="post" onreset="resetSliders()">
            <div class="form-group">
                <label>Nazwa</label>
                <input type="text" class="form-control bg-secondary text-light" minlength="5" maxlength="20" required="required" asp-for="Armor.Name" />
                <small>Długość od 5 do 20 znaków</small>
            </div>
            <div class="form-group">
                <label>Odporność na obrażenia</label>
                <input id="physical" class="mySlider" type="range" value="10" min="0" max="100" step="5" asp-for="Armor.DamageResistance" />
                <output>10</output>
            </div>
            <div class="form-text">
                <label>Odporność na magię</label>
                <input id="magic" class="mySlider" type="range" value="10" min="0" max="50" step="5" asp-for="Armor.MagicResistance" />
                <output>10</output>
            </div>
            <div class="text-center">
                <button type="submit" asp-page-handler="Create" class="btn btn-outline-success m-2">Zapisz</button>
                <button id="resetBtn" type="reset" class="btn btn-outline-warning m-2">Resetuj</button>
                <button type="button" class="btn btn-outline-danger m-2" onclick="ToggleColumn(0)">Anuluj</button>
            </div>
        </form>
    </div>
</div>

PageModel cs:

private readonly ApplicationDbContext _ctx;

    public ArmourModel(ApplicationDbContext ctx)
    {
        _ctx = ctx;
    }

    [BindProperty]
    public Armor Armor { get; set; }
    [BindProperty]
    public IEnumerable<Armor> Armors { get; set; }
    
    public void OnGet()
    {
        Armors = new GetArmors(_ctx).Get();                 
    }

    public async Task<IActionResult> OnPostCreateAsync()
    {
        await new CreateArmor(_ctx).Create(Armor);          
            
        return RedirectToPage("Armor");
    }

    public IActionResult OnPostLoadArmor(int id)
    {
        Armor item = _ctx.Armors.Find(id);

        if (item == null)
        {
            RedirectToPage("Armor");
        }

        Armor.Id = item.Id;
        Armor.Name = item.Name;
        Armor.DamageResistance = item.DamageResistance;
        Armor.MagicResistance = item.MagicResistance;

        return RedirectToPage("Armor");
    }

JS:

function ToggleColumn(type) {
        var armourTable = document.getElementById("armourTable");
        var armourForm = document.getElementById("armourForm");
        var resetBtn = document.getElementById("resetBtn");

        if (type == 0) {
            armourTable.style.display = "block";
            armourForm.style.display = "none";
            resetBtn.style.display = "inline-block";                
        }

        else {   
                armourForm.style.display = "block";
                armourTable.style.display = "none";                    
                setSlider("physical");
                setSlider("magic");
                
            if (type == 2) {
                    resetBtn.style.display = "none";
            }                    
        }
    } // ToggleColumn()

Solution

  • I modified it and also add some js codes to implement your needs, you can refer to the below codes:

    Armor.cshtml

    @page
    @model LastTemple.Pages.Create.ArmourModel
    @{ }
    <p class="text-center font-weight-bold mb-2">Zarządzaj pancerzami</p>
    
    <div class="row">
        <div class="col-5 p-1">
            <img src="~/img/armor.png" class="img-thumbnail-dark" />
        </div>
    
    
        <div class="col-7 pl-5 pr-5">
            <div id="armourTable" class="text-center">
    
                <button class="btn btn-outline-light mb-2" onclick="ToggleColumn(1)">Stwórz pancerz</button>
    
                <table class="table text-light text-center">
                    <thead>
                        <tr>
                            <th scope="col">Id</th>
                            <th scope="col">Nazwa</th>
                            <th scope="col">Odp. fiz.</th>
                            <th scope="col">Odp. mag.</th>
                            <th scope="col"></th>
                            <th scope="col"></th>
                        </tr>
                    </thead>
                    <tbody>
    
                        @foreach (var item in Model.Armors)
                        {
            <tr id="[email protected]">
                <th scope="row">@item.Id</th>
                <td>@item.Name</td>
                <td>@item.DamageResistance</td>
                <td>@item.MagicResistance</td>
                <td><button class="btn btn-outline-warning" name="edit" type="submit" onclick="ToggleColumn(2)">Edytuj</button></td>
                <td><form method="post"><button class="btn btn-outline-warning" type="submit" asp-page-handler="Delete" asp-route-id="@item.Id">Usuń</button></form></td>
            </tr>
    }
    
                    </tbody>
                </table>
            </div>
    
            <div id="armourForm" style="display:none" class="p-5">
                <form id="manipulateArmor" method="post" onreset="resetSliders()">
                    <input type="hidden" id="id" asp-for="Armor.Id" />
                    <div class="form-group">
                        <label>Nazwa</label>
                        <input type="text" id="nazwa" class="form-control bg-secondary text-light" minlength="5" maxlength="20" required="required" asp-for="Armor.Name" />
                        <small>Długość od 5 do 20 znaków</small>
                    </div>
    
                    <div class="form-group">
                        <label>Odporność na obrażenia</label>
                        <input id="physical" class="mySlider" type="range" value="10" min="0" max="100" step="5" asp-for="Armor.DamageResistance" />
                        <output>10</output>
                    </div>
    
                    <div class="form-text">
                        <label>Odporność na magię</label>
                        <input id="magic" class="mySlider" type="range" value="10" min="0" max="50" step="5" asp-for="Armor.MagicResistance" />
                        <output>10</output>
                    </div>
    
                    <div class="text-center">
                        <button id="createBtn" type="submit" asp-page-handler="Create" class="btn btn-outline-success m-2">Zapisz</button>
                        <button id="editBtn" type="submit" asp-page-handler="Update" class="btn btn-outline-success m-2">Edytować</button>
                        <button id="resetBtn" type="reset" class="btn btn-outline-warning m-2">Resetuj</button>
                        <button type="button" class="btn btn-outline-danger m-2" onclick="ToggleColumn(0)">Anuluj</button>
                    </div>
                </form>
            </div>
    
    
        </div>
    
        @section scripts{
            <script type="text/javascript">
                var form = document.getElementById("manipulateArmor");
                loadSettings();
                document.getElementById("physical").oninput = function () { setSlider("physical"); }
                document.getElementById("magic").oninput = function () { setSlider("magic"); }
    
                function loadSettings() {
                    setSlider("physical");
                    setSlider("magic");
                    ToggleColumn(0);
                }
    
                function resetSliders() {
                    window.requestAnimationFrame(function (timestamp) {
                        setSlider("physical");
                        setSlider("magic");
                    })
                }
    
                function setSlider(type) {
                    var slider = document.getElementById(type)
                
                    var value = (slider.value - slider.min) / (slider.max - slider.min) * 100
    
                    if (slider == null) {
                        alert("slider is null");
                    }
    
                    if (type == "physical") {
                        slider.style.background = 'linear-gradient(to right, #FF6B6B 0%, #FF0000 ' + value + '%, #000 ' + value + '%, black 100%)'
                    }
    
                    else {
                        slider.style.background = 'linear-gradient(to right, #0000FF 0%, #6600CC ' + value + '%, #000 ' + value + '%, black 100%)'
                    }
                    slider.nextElementSibling.value = slider.value
                };
    
            
                function ToggleColumn(type) {
                    var armourTable = document.getElementById("armourTable");
                    var armourForm = document.getElementById("armourForm");
                    var resetBtn = document.getElementById("resetBtn");
                    var createBtn = document.getElementById("createBtn");
                    var editBtn = document.getElementById("editBtn");
    
                    if (type == 0) {
                        armourTable.style.display = "block";
                        armourForm.style.display = "none";
                        editBtn.style.display = "none";
                        resetBtn.style.display = "inline-block";
                    }
                    else {
                        armourForm.style.display = "block";
                        armourTable.style.display = "none";
                        setSlider("physical");
                        setSlider("magic");
                        if (type == 2) {
                            var x = event.srcElement.parentElement.parentElement;
                            var id = x.children[0].innerHTML;
                            var name = x.children[1].innerHTML;
                            $("#id").val(id);
                            $("#nazwa").val(name);
                            editBtn.style.display ="inline-block"
                            resetBtn.style.display = "none";
                            createBtn.style.display = "none";
                        
                        } else {
                            editBtn.style.display = "none";
                            resetBtn.style.display = "inline-block";
                            createBtn.style.display = "inline-block";
                        }
                    }
                } 
            </script>
        }
    </div>
    

    Update function:

    public async Task<IActionResult> OnPostUpdateAsync()
    {
        var target = _ctx.Armors.Find(Armor.Id);
        if (target == null)
        {
            return RedirectToPage("Armor");
        }
        target.Name = Armor.Name;
        target.DamageResistance = Armor.DamageResistance;
        target.MagicResistance = Armor.MagicResistance;
    
        await _ctx.SaveChangesAsync();
        return RedirectToPage("Armor");
    }
    

    Result:

    enter image description here