Laravel 5.5 Controller#destroy DI won't inject model - laravel

I have resource controller with following destroy method:
public function destroy(ClinicImage $clinicImage)
{
$clinicImage->delete();
return redirect()->back()->with('success', 'Изображение удалено');
}
Also I have grid with following lines:
<td>
<div class="btn-group btn-group">
<button type="button" data-url="{{route('admin.clinic-image.destroy', [$clinic->id, $image->id])}}" class="btn btn-danger">
<i class="fa fa-remove fa-fw"></i>
</button>
</div>
</td>
And finally I have function to send form on button click:
$('.table').find('.btn.btn-danger').click(function(){
var form = makeForm({_method: 'DELETE'},{action: $(this).data('url')});
form.submit();
});
function makeForm(data, options) {
var form = document.createElement('form');
form.method = 'POST';
var token = document.createElement('input');
token.name = '_token';
token.value = jQuery('meta[name="csrf-token"]').attr('content');
form.appendChild(token);
jQuery.each(data, function(key, value){
var input = document.createElement('input');
input.name = key;
input.value = value;
form.appendChild(input);
});
if(Object.keys(options).length) {
jQuery.each(options, function(option, value){
form[option] = value;
});
}
document.body.appendChild(form);
return form;
}
When i sending form to /admin/clinic/1/clinic-image/1, I get following error:
Type error: Argument 1 passed to App\Http\Controllers\Admin\ClinicImageController::destroy() must be an instance of App\ClinicImage, string given
Controller routes.
So my question is: Why DI do not recognize my route and model id?

Try this one:
public function destroy($clinic, $clinicImage)
{
$clinicImage = ClinicImage::where('id', $clinic)->where('image', $clinicImage); //I'm guessing the name of the columns.
$clinicImage->delete();
return redirect()->back()->with('success', 'Изображение удалено');
}

Actually, you're using wrong argument name in the controller.
Change your signature in a controller.
Instead of $clinicImage change it to $clinic_image
Option 1 : Change in controller
public function destroy(ClinicImage $clinic_image) //$clinicImage to $clinic_image
{
$clinicImage->delete();
return redirect()->back()->with('success', 'Изображение удалено');
}
Option 2 :
Change parameter in route file:
Route::delete('/admin/clinic/{clinic}/clinic-image/{clinicImage})->name('');

Try this in your controller file
public function destroy(ClinicImage $clinicImage)
{
$clinicImage->delete();
return redirect()->back()->with('success', 'Изображение удалено');
}
And in your view file
<td>
<div class="btn-group btn-group">
<button type="button" data-url="{{route('admin.clinic-image.destroy', [$clinic->id])}}" class="btn btn-danger"> (over here you need to pass 1 id at a time which you need to delete)
<i class="fa fa-remove fa-fw"></i>
</button>
</div>
</td>

Related

Updating parent model on ajax call from partial view

I have a .net core application that has a page for changing settings. There is a visual representation of the page here:
https://i.imgur.com/R6MyDlo.png
This view (blue) contains a number of buttons (black) for changing tabs to display different settings pages. There is also a partial (red) that contains a number of other partials for the settings. This partial updates when switching between tabs or updating settings. Settings are not saved to the hardware or database until the user clicks save in the sidebar (green).
The settings come from a json file that can be several 100 kilobytes and are stored as an object in the view model. This view model is shared between all the partial views. When the user updates something it calls an ajax function sending the model as json. I have included an example for changing settings below but all follow a similar pattern.
Main view (blue):
#model Project.ViewModels.TestViewModel
<div class="row" id="body-row">
#Html.Partial("_SidebarPartial") // green
<div class="col">
<div class="row top-margin">
<div class="col-sm-12 col-md-12 col-lg-9">
<button id="generalButton" class="btn btn-primary mr-2 mb-2" onclick="LoadGeneral()">General</button>
#for (int i = 0; i < Model.Config.Machines.Count; i++)
{
<button id="#("Machine" + (i + 1))" class="btn btn-primary mr-2 mb-2" onclick="LoadMachine(#i)">
#Model.Config.Machines[i].Name
</button>
}
</div>
<div id="TestConfig" class="col-sm-12 col-md-6 col-lg-9">
#Html.Partial("Test/_ConfigPartial", Model) // red
</div>
</div>
</div>
</div>
Sample ajax call to update UI:
function UpdateMode(i, j) {
var viewModel = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model));
data = JSON.stringify({ mode: i, selectedProgram: j, model: viewModel })
$.ajax({
type: "POST",
data: data,
url: "https://localhost:44365/Test/UpdateMode",
contentType: "application/json"
}).done(function (res) {
$("#TestConfig").html(res)
});
}
Controller actions:
public IActionResult Config()
{
Model = new TestViewModel();
HttpContext.Session.SetObjectAsJson("Model", Model);
return View(HttpContext.Session.GetObjectFromJson<MachineViewModel>("Model"));
}
[HttpPost]
public PartialViewResult UpdateMode([FromBody]DtoTestModel model)
{
model.Model.Config.Programs[model.SelectedProgram].Mode = (ModeType) model.Mode;
HttpContext.Session.SetObjectAsJson("Model", model.Model);
return new PartialViewResult
{
ViewName = "~/Views/Shared/_GeneralPartial.cshtml",
ViewData = new ViewDataDictionary<TestViewModel>(ViewData, model.Model)
};
}
Temporary view model class. This is because [FromBody] only accepts one parameter and the updated model values are not posted to the server:
public class DtoTestModel
{
public TestViewModel Model { get; set; }
public int SelectedProgram { get; set; }
}
ViewModel:
public class TestViewModel
{
public Config TestConfig { get; set; }
public int Mode { get; set; }
public TestViewModel()
{
using (var reader = File.OpenText(#"temp\Config.txt"))
{
string json = reader.ReadToEnd();
TestConfig = JsonConvert.DeserializeObject<Config>(json);
}
}
}
Currently though the model stays the same throughout for the parent. So when a setting is updated it is only the changed version until the next setting change. I need a way to also update the parent model without refreshing the page.

how to use ajax.beginform with foreach and model to create button for each li inside a partialview ul list? (the buttons are there to remove items/li)

I am creating an mvc project and in it I am using foreachinside a partial view to fill an ul list in the view . My foreach collection is a list of model and I want to create a button for each model/li element that submits the current model to a PartialViewResult which then will delete the model from databse. So I try something like this:
#model WebApplication6.Models.Lang_User
#{ WebApplication6.Models.Entities db = new WebApplication6.Models.Entities();
List<WebApplication6.Models.Lang_User> langlist=db.Lang_User.Where(x => x.UserID ==Model.UserID).ToList();
}
{
#foreach (WebApplication6.Models.Lang_User item in langlist)
{using (Ajax.BeginForm("DilSil", new AjaxOptions())) {
<li id="#item.ID" class="list-group-item">#item.Languages.Language <button type="submit" class="btn btn-warning"></button></li>
}
}
But now i need to make something inside ajaxforms. When i submit one of the forms in ul list. It must submit the #item so is there a way to do it?
edit1: Delete PartialViewResult
public PartialViewResult DilSil(Lang_User dil)
{
db.Lang_User.Remove(dil);
db.SaveChanges();
System.Threading.Thread.Sleep(3000);
return PartialView("_DilPartial", dil);
}
All you need to do is, to send the unique Id of the entity in the form post. To do that, Keep the id in an input field, which is hidden inside the form. The input element name should match with your parameter name. When user clicks on the button, the form data will be submitted, including the hidden input
using (Ajax.BeginForm("DilSil", new AjaxOptions() { }))
{
<li id="#item.ID" class="list-group-item">
This is #item.ID
<input type="hidden" value="#item.ID" name="id" />
<button type="submit" class="btn btn-warning">Delete</button>
</li>
}
Now in your action method, read the id, get the entity and delete it. You can probably return the list of current data (read it again from db) and pass that and update the UI using UpdateTargetId and InsertionMode attributes or return a JSON response which you can handle in your OnSuccess handler
In your case, your li item id is same is the id of the entity .So you can return that information back to the client and the OnSuccess handler method can delete that element from the DOM
[HttpPost]
public ActionResult DilSil(int id)
{
var dil=db.Lang_User.Find(id);
db.Lang_User.Remove(dil);
db.SaveChanges();
return Json(new { status = "success" , id=id });
}
Now add an OnSuccess handler to your AjaxOptions when using Ajax.BeginForm helper method to render the form. This will be a javascript function which will be called after the ajax call is done. The response from server will be passed to this function.
using (Ajax.BeginForm("DilSil", new AjaxOptions() { OnSuccess = "DeleteDone" }))
{
<li id="#item.ID" class="list-group-item">
This is #item.ID
<input type="hidden" value="#item.ID" name="id" />
<button type="submit" class="btn btn-warning">Delete</button>
</li>
}
Now define the javascript method which reads the json response and delete the li item
function DeleteDone(a, b, c) {
if (a.status === 'success') {
$("#" + a.id).remove();
}
}

nested partial View calling HttpPost method 2 times

I have seen this question being asked few times here , but solution I saw are not generic , they are related to their specific code ..
I need to rectify the Work done by previous developer , the flow of ajax calls are wrong in code
In my Situation I have views like :
1.Index (Main View)
2.ParentCategoryList (partial View inside Index)
3. AddChild (partial View inside ParentCategoryList )
4. childCategorytree (Seperate View )
Problem is that from 2nd nested View (AddChild ) , whhen i click on save button ,httpost method is calling twice
My Index View
<div>
<div class="content" id="divparent">
</div>
<div class="content" id="dvChild">
</div>
</div>
its script
#section scripts{
<script type="text/javascript">
$('document').ready(function () {
//------------
$.get('#Url.Action("ParentCategoryList", "List")', function (data) {
$("#divparent").html("");
$("#divparent").html(data);
});
})
function addnewchild(url) {
$.get(url, function (data) {
$("#dvChild").html("");
$("#dvChild").html(data);
});
}
</script>
}
First Partial View inside Index (ParentCategoryList.cshtml)
#foreach (Bmsa.UI.Models.ListsResultModel data in Model)
{
<tr> <td><a onclick="addnewchild('#Url.Action("AddChild",
"List", new { id = #data.listID })')" >
</a> </td></tr> } </tbody> </table>
2nd Nested Partial View inside ParentCategoryList
#using (Ajax.BeginForm("AddChild", "List", new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "dvChild"
}))
{
<div > <input type="submit" value="Save" /></p></div>}
and Controller methods
public ActionResult ParentCategoryList()
{
//Code
return PartialView("ParentCategoryList", categoryList); }
//GET Operation to Load this View
public ActionResult AddChild(int id)
{
ViewBag.ParentID = id;
ListsAddModel addchild = new ListsAddModel();
addchild.parentListId = id;
return PartialView("AddChild", addchild);
}
[HttpPost] (**this method is calling twice--this is the problem** )
public ActionResult AddChild(ListsAddModel model,int id)
{
//Code
return RedirectToAction ("ChildCategoryListTree", new { id = model.parentListId });
}
and childCategorytree Partial view (also blank one)
I am not able to prevent this method to called twice . I tried e.preventDefault() in $.ajax call , but it is not working ...
I have tried to minimise the code , I think the problem is in RedirectToAction , but I am not sure
Any Help would be appreciated

How to show value inside input filed on change of drop down value using zend framework 2

I am trying to create an onchange event in zend framework 2. suppose if i change option form dropdown list then the related value will be shown on input field .Here my dropdown works fine .but when i am trying to change dropdown list then there is no value shows on my input field.but the data comes.but not display on broweser.So tell me how it is possible.
Here is My Controller
public function propratingAction()
{
$projectName = $this->propinquity()->projectName();
if($this->getRequest()->isPost())
{
$project =$this->getRequest()->getPost('project');
$projectD = json_decode($project, true);
//print_r($projectD);
$propinquityindex=$this->propinquity()->getproprating($projectD);
$propratingHTML=$this->propratingHTML($propinquityindex);
print_r($propratingHTML);
}
$viewModel = new ViewModel();
$viewModel->setVariables(array('key' => 'value'))
->setTerminal(true);
return $viewModel;
}
public function propratingHTML($propinquityindex){
$html='';
foreach ($propinquityindex as $value) {
# code...
$html .='<input type="text" value="'.$value['critics_rating'].'"/>';
}
print_r($html);
$viewModel = new ViewModel();
$viewModel->setVariables(array("key" => "value"))
->setTerminal(true);
return $viewModel;
}
Here is view part
<div style="display:inline-block; margin-left:55px; margin-top:20px;">
<select style="width:12.5em;" id="project_id" onchange="getsectorindexAjax();"
data-placeholder="Project Name" class="selectError2" data-rel="chosen"
name="project_id" >
<option value="">--select project--</option>
<?php if($this->projectName){
foreach($this->projectName as $val){
echo '<option value="'.$val['project_id'].'">'.$val['Project_name'].'
</option>';
}
} ?>
</select>
</div>
<div class="main" style="display:inline-block; margin-left:10px;margin-top:20px;">
CRc Rating
<input style="width:20em;height:2.7em;" name="critics_rating"
id="critics_rating" type="text" value="">
</div>
ajax call
function getsectorindexAjax()
{
require(["dojo/request", "dojo/query","dijit/registry"], function(request, registry) {
// Locate the JS object.
var project = dojo.byId("project_id").value;
//alert(project);
request.post("http://localhost/admin/propinquity/proprating",{
data : {
project : JSON.stringify(project)
}
}).then(function(text) {
dojo.byId("critics_rating").innerHTML = text;
console.log("return data : " + text);
});
});
}
So suggest me how can i show value inside input field when my dropdown value is change.
You can try something like this :
var dropdown= dijit.byId("project_id"); //get the select element
//on change event
dropdown.on('change', function(evt) {
//get the selected value
var project = dropdown.get("value");
//your ajax request
request.post("http://localhost/admin/propinquity/proprating",{
data : {
project : JSON.stringify(project)
}
}).then(function(text) {
dijit.byId("critics_rating").attr("value", text);
console.log("return data : " + text);
});
});

Jquery Accordion Validation Not working when rendering Partial View through $.ajax call

Hi friends,I am working on MVC 4 Razor and I am stuck in a situation
where Employee Personal Details form is to be filled in
steps(wizard)..for which i used jquery accordion control..for every
step i put an accordion..The html in each accordion section is
rendered from partial view through ajax call on every click of
respective accordion (i.e. <h3></h3> tag)..
On page load first/top accordion is active by default. My problem is
to restrict the user to click on next accordion until he/she fills the
presently active accordion correctly..
Here is my full code:
View:
#model XXX.ViewModels.PersonalDetailsViewModel
#{
ViewBag.Title = "PersonalDetails";
Layout = "~/Views/Shared/Template.cshtml";
}
#using (Html.BeginForm("Lifestyle", "Apply", FormMethod.Post, new { id = "personalDetailForm" }))
{
<div class="centerdiv margin_top20">
<div class="row">
#Html.ValidationSummary(true, "Please Correct the following errors:")
</div>
<div style="width: 1000px;">
<div id="Personalaccordion" class="acordion_div" style="padding: 10px; float: left;">
<h3 class="acordion_div_h3" onclick="javascript:PersonalModule.GetRenderingView('Apply/GetBasicDetailsView','personalDetailForm','BasicDetailsDiv');">
<p>
Basic Details<span id="BasicDetailsDivExp"></span>
</p>
</h3>
<div id="BasicDetailsDiv">
</div>
<h3 class="acordion_div_h3" onclick="javascript:PersonalModule.GetRenderingView('Apply/GetPersonalAddressView','personalDetailForm','PersonalAddressDiv');">
<p>
Address<span id="PersonalAddressDivExp"></span></p>
</h3>
<div id="PersonalAddressDiv">
</div>
</div>
<ul id="conlitue_ul" style="margin-top: 20px;">
<li style="margin-left: 140px;">
<input type="submit" class="compareBtn float_lt" value="Continue Buying >" id="continue" /></li>
</ul>
</div>
</div>
}
#Scripts.Render("~/bundles/PersonalDetails")
<script type="text/javascript">
PersonalModule.GetRenderingView('Apply/GetBasicDetailsView', '', 'BasicDetailsDiv');
</script>
My Controller:
public ActionResult PersonalDetails(int leadId)
{
var personalDetailsViewModel = LeadHelper.GetPersonalDetails(leadId);
return View(personalDetailsViewModel);
}
public ActionResult GetBasicDetailsView(PersonalDetailsViewModel personalDetailsViewModel)
{
if (personalDetailsViewModel.BasicDetails == null)
{
ModelInitializerHelper.InitilaizeBasicDetailsVModel(personalDetailsViewModel);
}
ModelInitializerHelper.InitializeBasicLookup(personalDetailsViewModel);
return PartialView("Personal/BasicDetails", personalDetailsViewModel);
}
public ActionResult GetPersonalAddressView(PersonalDetailsViewModel personalDetailsViewModel)
{
if (personalDetailsViewModel.PersonalAddressDetails == null)
{
ModelInitializerHelper.IntializePersonalAddressVModel(personalDetailsViewModel);
}
ModelInitializerHelper.InitializePersonalAddressLookup(personalDetailsViewModel);
return PartialView("Personal/PersonalAddress", personalDetailsViewModel);
}
My JS :
var PersonalModule = {
GetRenderingView: function (url, formId, containerID) {
var applicationurl = ApplicationRoot + '/' + url;
var objects = $('#BasicDetailsDivExp , #PersonalAddressDivExp' );
viewDivID = containerID;
GetAccordionView(applicationurl, formId, objects, containerID, 'accordion_plus', 'accordion_minus');
}
}
GetAccordionView: function (url, formId, objects, containerID, accordion_plus, accordion_minus) {
var formObjectData = null;
if (formId != undefined) {
formObjectData = $("#" + formId).serialize();
}
var renderView = function (data) {
$('#' + containerID).innerHtml = data;
}
ExpandAccordion(objects, containerID, accordion_plus, accordion_minus);
DoServerRequest(url, formObjectData, renderView);
}
ExpandAccordion: function (objects, spanIconID, accordion_plus, accordion_minus) {
var Objects = objects;
Objects.removeClass(accordion_minus);
Objects.addClass(accordion_plus);
$('#' + spanIconID + 'Exp').removeClass(accordion_plus).addClass(accordion_minus);
if (Browser.ie7) {
Objects.css("margin-top", "-22px");
}
}
DoServerRequest: function (url, data, funSuccess) {
$.ajax({
type: "POST",
url: url,
data: data,
async: false,
dataType: "json",
success: funSuccess,
error: function (errorResponse) {
if (errorResponse.readyState == 4 && errorResponse.status == 200) {
renderCurrentView(errorResponse.responseText)
}
else {
alert(errorResponse.responseText);
}
}
});
}
Please somebody help..I have heard lots of good thing about this forum
and this is my first Question...Thanks in advance..
I have removed my jquery validation attempt as it made the code
garbage thing Now I dont know what to write and where to write
If you are trying to validate data that has been added to form via Ajax after page load then you will need to use the rules method and add rules for these new elements. Jquery Validate has no way of knowing about them otherwise.
Example
Once you have loaded your new content via Ajax you need to find each element and add the necessary rules to them.
$('#yourDiv').find(".newElements").rules("add", {
required: true,
messages: {
required: "Bacon is required"
}
});
If you are using unobtrusive validate you may need to add your new elements to that also. See this SO question for more details.
Validating the Form
To check if the fields are valid, you will need to validate the form on click. This can be done using .validate(). You can then check if the form validated using .valid()
Example
$('#yourForm').validate();
if(!$('#yourForm').valid()) {
alert('Bacon is required');
}

Resources