AngularJS can't pass $index from bootstrap modal window - javascript

I'm banging my head against the wall here. I'm using ng-repeat to populate a table. Inside each row i have 2 buttons, one for updating the row content and for uploading files. The upload button opens a bootstrap modal window, where the user selects the files and clicks on submit.
The submit button uses ng-click to run a function which uses $index as parameter. But the $index value is always the same no matter which row is selected.
The thing I don't understand is that I use the exact same syntax (although outside of a modal window) on my update button, which works just fine.
HTML:
<tr ng-repeat="item in items | filter:search " ng-class="{'selected':$index == selectedRow}" ng-click="setClickedRow($index)">
<td>{{$index}}</td>
<td ng-hide="idHidden" ng-bind="item.Id"></td>
<td ng-hide="titleHidden">
<span data-ng-hide="editMode">{{item.Title}}</span>
<input type="text" data-ng-show="editMode" data-ng-model="item.Title" data-ng-required />
<td>
<button type="button" class="btn btn-primary uploadBtn" data-ng-show="editMode" data-toggle="modal" data-target="#uploadModal">Upload file <i class="fa fa-cloud-upload"></i></button>
<!-- Upload Modal -->
<div class="modal fade" id="uploadModal" tabindex="-1" role="dialog" aria-labelledby="uploadModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="uploadModalLabel">Options</h3>
</div>
<div class="modal-body">
<h4>Upload Documents</h4>
<form>
<div class="form-group">
<select data-ng-model="type" class="form-control" id="fileTypeSelect">
<option value="Policy">Policy</option>
<option value="SOP">SOP</option>
</select>
<br>
<div class="input-group"> <span class="input-group-btn">
<input type="file" id="file">
</span>
</div>
<br>
<button type="button" class="btn btn-default" data-ng-click="uploadAttachment($index, type)">Upload</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
<button type="button" data-ng-hide="editMode" data-ng-click="editMode = true;" class="btn btn-default pull-right">Edit <i class="fa fa-pencil-square-o"></i></button>
<button type="button" data-ng-show="editMode" data-ng-click="editMode = false; updateItem($index)" class="btn btn-default">Save</button>
<button type="button" data-ng-show="editMode" data-ng-click="editMode = false; cancel()" class="btn btn-default">Cancel</button>
</td>`
JS:
$scope.uploadAttachment = function executeUploadAttachment(index, type) {
var listname = "Risk Register";
var id = $scope.items[index].Id;
console.log(indexID);
readFile("uploadControlId").done(function(buffer, fileName) {
uploadAttachment(type, id, listname, fileName, buffer).done(function() {
alert("success");
}).fail(function() {
alert("error in uploading attachment");
})
}).fail(function(err) {
alert("error in reading file content");
});
}
So the function uploadAttachment($index, type) which is triggered by ng-click doesn't pass the right index number. It always passes the same, no matter what row it is clicked in.
I have omitted some of the code that is irrelevant. If needed i can provide the whole thing.
Any suggestions to what I am missing?
Edit:
I have tried to implement DonJuwe suggestions.
I have added this inside my controller:
$scope.openModal = function(index) {
var modalInstance = $modal.open({
templateUrl: 'www.test.xxx/App/uploadModal.html',
controller: 'riskListCtrl',
resolve: {
index: function() {
return index;
}
}
});
};
This is my modal template:
<div class="modal-header">
<h3 class="modal-title" id="uploadModalLabel">Options</h3>
</div>
<div class="modal-body">
<h4>Upload Documents</h4>
<form>
<div class="form-group">
<select data-ng-model="type" class="form-control" id="fileTypeSelect">
<option value="Policy">Policy</option>
<option value="SOP">SOP</option>
</select>
<br>
<div class="input-group"> <span class="input-group-btn">
<input type="file" id="file">
</span>
</div>
<br>
<button type="button" class="btn btn-default" data-ng-click="uploadAttachment($index, type)">Upload</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
And finally my function which resides inside RiskListCtrl (the only controller i use):
$scope.uploadAttachment = function executeUploadAttachment(index, type) {
var listname = "Risk Register";
var id = $scope.items[index].Id;
console.log(indexID);
readFile("uploadControlId").done(function(buffer, fileName) {
uploadAttachment(type, id, listname, fileName, buffer).done(function() {
alert("success");
}).fail(function() {
alert("error in uploading attachment");
})
}).fail(function(err) {
alert("error in reading file content");
});
}
It seems that $scope.items[index].Id is empty. Error: Cannot read property 'Id' of undefined

The modal window has its own scope. That means you need to resolve data you want to pass into the modal's scope. To do so, use resolve within the modals open(options) method.
Before I will give you an example, I want to suggest having only one modal for all your table items. This will let you keep a single template where you can easily use id (now, you create a template for each of your table items which is not valid). Just call a controller function and pass your $index:
<button type="button" class="btn btn-primary uploadBtn" data-ng-show="editMode" ng-click="openModal($index)">Upload file <i class="fa fa-cloud-upload"></i></button>
In your controller, create the modal instance and refer to the template:
$scope.openModal = function(index) {
var modalInstance = $modal.open({
templateUrl: 'myPath/myTemplate.html',
controller: 'MyModalCtrl',
resolve: {
index: function() {
return index;
}
}
});
};
Now you can access index in your MyModalCtrl's scope by injecting index:
angular.module('myModule', []).controller('MyModalCtrl', function($scope, index) {
$scope.index = index;
});

Since, you are getting the index value outside model then you can also use ng-click and then call a function in your controller and store the index value in a temporary variable and then when you are using submit button then just take make another variable and assign the value of temporary variable to your variable. for example:
<button type="button" data-ng-show="editMode" data-ng-click="editMode = false; updateItem($index)" class="btn btn-default">Save</button>
and then make a function in your controller
$scope.updateItem = functon(index)
{
$scope.tempVar = index;
}
now use the value of tempVar in you function
$scope.uploadAttachment = function executeUploadAttachment(index, type) {
var index = tempVar; //assign the value of tempvar to index
var listname = "Risk Register";
var id = $scope.items[index].Id;
console.log(indexID);
readFile("uploadControlId").done(function(buffer, fileName) {
uploadAttachment(type, id, listname, fileName, buffer).done(function() {
alert("success");
}).fail(function() {
alert("error in uploading attachment");
})
}).fail(function(err) {
alert("error in reading file content");
});
}

Related

Bootstrap Modal inside a table populated from a partial

This is follow up question on this (Bootstrap Modal Confirmation using ASP.Net MVC and a table)
Using MVC .NetCore, I populate a "partial" view and a Table (called _Match_StatsViewAll.cshtml under a directory of the same name of my controller Match_Stats).
It's being called from an Indexview:
public async Task<ViewResult> Match_StatsIndex(string message, string comp_id, string match_id, string team_id)//ACTION METHOD/View Results
Within that table (code below) , a list of records. Each row have a button to edit or delete. To delete a record, I need to have 4 IDs since the PK is made of those 4 keys. I was able to make it work with a javascript, however, I did not like the "confirm" display being produced. Thanks to this post, I was able to add a modal for each rows in the table and delete the record. However now, If I use the original json call to refresh the partial model (that only refresh the table), I have this screen:
Here is a Row being populated from my Model:
<td>
<div>
#{i++; }
<a onclick="showInPopup('#Url.Action("Match_StatsCreateOrEdit","Match_Stats",new {comp_id=item.Match_Stats.Comp_Id, team_id=item.Match_Stats.Team_Id,match_id=item.Match_Stats.Match_Id, match_Stat_Id=item.Match_Stats.Match_Stat_Id},Context.Request.Scheme)','Update A Stat')" class="btn btn-primary btn-xs"><i class="fas fa-pencil-alt"></i> Edit</a>
<form asp-action="Match_StatsDelete" asp-route-comp_Id="#item.Match_Stats.Comp_Id" asp-route-team_Id="#item.Match_Stats.Team_Id" asp-route-Match_Id="#item.Match_Stats.Match_Id"
asp-route-Match_Stat_Id="#item.Match_Stats.Match_Stat_Id" onsubmit="return jQueryAjaxDelete(this)" class="d-inline">
<button type="submit" class="btn btn-warning btn-xs"><i class="fas fa-trash"></i> Delete</button>
</form>
#*//add the button to launch the modal*#
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#modal-removeplayers_#i"><i class="fas fa-trash"></i> Delete modal</button>
<div class="modal fade" id="modal-removeplayers_#i">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Confirmation needed</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Do you really want to delete this record ?</p>
</div>
<div class="modal-footer justify-content-between">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<form asp-action="Match_StatsDelete" asp-route-comp_Id="#item.Match_Stats.Comp_Id" asp-route-team_Id="#item.Match_Stats.Team_Id" asp-route-Match_Id="#item.Match_Stats.Match_Id"
asp-route-Match_Stat_Id="#item.Match_Stats.Match_Stat_Id" onsubmit="return jQueryAjaxDeleteDirect(this)" class="d-inline">
<button type="submit" class="btn btn-warning btn-xs"><i class="fas fa-trash"></i> Delete Json</button>
</form>
</div>
</div>
</div>
</div>
</div>
</td>
In my controller - calling the delete :
public async Task<IActionResult> Match_StatsDelete(string comp_id, string team_id, string match_id, string match_stat_id)
{
// Wrap the code in a try/catch block
try
{
var deleteok = _match_statsRepository.Delete(entity);
if (deleteok != null)
{
//Code Here to populate my table only since this is a partial view inside a page
return Json(new { isValid = true, html = JavaScriptConvert.RenderRazorViewToString(this, "_Match_StatsViewAll", myPartialmodelpopulated) });
}
else
{
ModelState.AddModelError("", "Could not Delete Match");
return RedirectToAction("MatchIndex", new { message = "Success", comp_id });
}
}
catch (Exception ex)
{
// Log the exception to a file.We discussed logging to a file
//......More code here for the log has been removed //
return View("Error");
}
}
Here is the Javascript:
jQueryAjaxDeleteDirect = form => {
try {
$.ajax({
type: 'POST',
url: form.action,
data: new FormData(form),
contentType: false,
processData: false,
success: function (res) {
$('#view-all').html(res.html);
$.notify('Deleted Successfully !', {
globalPostion: 'Top Center',
className: 'success'
});
},
error: function (err) {
console.log(err)
}
})
} catch (ex) {
console.log(ex)
}
//prevent default form submit event
return false;
}
The " return Json" call works fine if I use the original code (so no MODAL form - just the javascript "confirm") .
Thank you for the help!

ng-click in modal not calling function in component

I am trying to figure out how to get this working.
I am using AngularJS because I do not want to load the complete NPM of Angular and we are using Razor Syntax extensively for the Web Layer
On the Create.cshtml page
<button type="button" ng-click="addApp('Cheese')"
class="btn-sm btn-default no-modal">
Add Applications
</button>
Below is how I have the directory stucture is as follows:
WebLayer
+--wwwroot
+--js
+--applications (Feature)
+applications.component.js
+applications.module.js
+application.template.html
+--delegates (Feature)
+delegates.component.js
+sames as above
+--sponsor-applictions
+same as above
+--lib
+angularjs and all other angularjs files
+app.config.js
+app.module.js
Now I have no problems with getting data below in the sponsor-applictions.component.js I am getting my JSON Object Models arrays from my API.
//Author Moojjoo
//Date 5/3/2019
//sponsor-applications
'use strict';
var testUrl = window.location.hostname;
if (testUrl.includes("localhost")) {
var apiUrl = 'https://localhost:44364';
}
else if (testUrl.includes("uat")) {
var apiUrl = 'https://localhost:44364'; //TODO when the URL is decided for UAT
}
else {
var apiUrl = 'https://localhost:44364'; //TODO when the URL is decided for PRD
}
// Register `sponsorApplications` component, along with its associated controller and template
angular.
module('App').
component('sponsorApplications', {
templateUrl: '../../js/sponsor-applications/sponsor-applications.template.html',
controller: ['$scope', '$http', function SponsorApplications($scope, $http) {
var user_id = $("#User_Id").val();
if (user_id != "") {
$http.get(apiUrl + '/api/v1/Sponsors/' + user_id + '/Applications').then(function successCallback(response) {
$scope.sponsorApplications = response.data;
console.log($scope.sponsorApplications);
}, function errorCallback() {
//var type = 'warning';
//var title = 'User Lookup Required!';
//var body = 'Please enter a User Login ID for lookup'
alert('Please try again later, network error, email sent to application administrator')
});
}
//TODO - Have to get rows from Modal to Page
// Add Rows
$scope.addApp = function (arg) {
debugger;
console.log(arg);
alert(arg);
//$scope.table.push($scope.newApp);
// $scope.newApp = new Object();
};
// Remove Rows
$scope.remove = function (index) {
debugger;
$scope.sponsorApplications.splice(index, 1);
};
}
]
});
I am banging my head against the keyboard trying to figure out why the addApp('Cheese') will not event for for ng-click. $scope.remove function works without any issues.
I really need to understand what I am missing. Thank you and if you need more details simply add a comment.
Edit adding full code
app.config
'use strict';
angular.
module('App').
config(['$routeProvider',
function config($routeProvider) {
$routeProvider.
when('/Sponsors/Create', {
template: '<sponsor-applications></sponsor-applications>'
}).
when('/Sponsors/Create', {
template: '<applications></applications>'
}).
when('/Sponsors/Create', {
template: '<sponsor-delegates></sponsor-delegates>'
}).
when('/Sponsors/Create', {
template: '<delegates></delegates>'
})
}
]);
app.module.js
'use strict';
angular.module('App', [
'ngRoute',
'sponsorApplications',
'applications',
'sponsorDelegates',
'delegates'
])
.run(function () {
console.log('Done loading dependencies and configuring module!');
});
sponsor-applications.component.js
//Author Robert B Dannelly
//Date 4/8/2019
//sponsor-applications
'use strict';
var testUrl = window.location.hostname;
if (testUrl.includes("localhost")) {
var apiUrl = 'https://localhost:44364';
}
else if (testUrl.includes("uat")) {
var apiUrl = 'https://localhost:44364'; //TODO when the URL is decided for UAT
}
else {
var apiUrl = 'https://localhost:44364'; //TODO when the URL is decided for PRD
}
// Register `sponsorApplications` component, along with its associated controller and template
angular.
module('App').
component('sponsorApplications', {
templateUrl: '../../js/sponsor-applications/sponsor-applications.template.html',
controller: ['$scope', '$http', function SponsorApplications($scope, $http) {
var user_id = $("#User_Id").val();
if (user_id != "") {
$http.get(apiUrl + '/api/v1/Sponsors/' + user_id + '/Applications').then(function successCallback(response) {
$scope.sponsorApplications = response.data;
console.log($scope.sponsorApplications);
}, function errorCallback() {
//var type = 'warning';
//var title = 'User Lookup Required!';
//var body = 'Please enter a User Login ID for lookup'
alert('Please try again later, network error, email sent to application administrator')
});
}
//TODO - Have to get rows from Modal to Page
// Add Rows
$scope.addApp = function (arg) {
debugger;
console.log(arg);
alert(arg);
//$scope.table.push($scope.newApp);
// $scope.newApp = new Object();
};
// Remove Rows
$scope.remove = function (index) {
debugger;
$scope.sponsorApplications.splice(index, 1);
};
}
]
});
sponsor-applications.module.js
'use strict';
// Define the `sponsorApplicaitons` module
angular.module('sponsorApplications', []);
sponsor-applications.template.html
<style>
/* Overwrites */
.btn {
width: 100%;
}
</style>
<table class="table-bordered table-striped" style="width:100%;">
<thead style="font-weight:bold">
<tr>
<td>Remove</td>
<td>Application ID</td>
<td>Application Name</td>
</tr>
</thead>
<!-- The naming must be exact application matches the $scope.sponsorApplications
in sponsor-applications.component.js-->
<tr ng-repeat="app in sponsorApplications">
<td>
<a class="btn" ng-click="remove($index)"><i class="fa fa-times" aria-hidden="true"></i></a>
</td>
<td>{{ app.application_ID }}</td>
<td>{{ app.application_Name }}</td>
</tr>
</table>
Create.cshtml -- ASP.NET Core w/ Razor Syntax ----
#model WEB.ViewModels.AddSponsorViewModel
#using WEB.HtmlHelpers
#{
ViewData["Title"] = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<!-- Alert Display will be used as a standard on all page simply add this to your page
https://www.trycatchfail.com/2018/01/22/easily-add-bootstrap-alerts-to-your-viewresults-with-asp-net-core/
https://www.trycatchfail.com/2018/02/21/easy-bootstrap-alerts-for-your-api-results-with-asp-net-core/-->
#await Html.PartialAsync("~/Views/Shared/_StatusMessages.cshtml")
<h2>Sponsor Information</h2>
<form asp-action="Create" id="CreateSponsor">
#Html.AntiForgeryToken()
#*<input type=hidden asp-for="User_ID" />*#
<input type="hidden" id="User_Id" name="User_Id" value="" />
<div class="form-horizontal">
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="col-md-12">
<row>
<div class="form-group col-md-5">
<label asp-for="Domain_ID" class="control-label"></label>
<br />
<input asp-for="Domain_ID" class="form-control" />
<span asp-validation-for="Domain_ID" class="text-danger"></span>
</div>
<div class="col-md-2">
</div>
<div class="form-group col-md-5">
<label asp-for="Name" class="control-label"></label>
<br />
<input asp-for="Name" class="form-control" />
#*#Html.AutocompleteFor(model => Core.Models.SearcherUser.Name, model => Core.Models.SearcherUser.Email, "GetSponsor", "Approval", false)*#
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</row>
</div>
<div class="col-md-12">
<row>
<div class="form-group col-md-12">
<label asp-for="Email" class="control-label"></label>
<br />
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</row>
</div>
<div class="col-md-12" style="margin-top:20px">
<row>
<div class="col-md-6">
<strong>Delegates</strong> <asp:button formnovalidate="formnovalidate" id="addDelegate" style="cursor: pointer" class="btn-xs btn-primary" data-toggle="modal" data-target="#delegatesModal">Add</asp:button>
<!-- AngularJS defined in wwwroot > js > sponsor-applications -->
<sponsor-delegates></sponsor-delegates>
</div>
<div id="divMyAppCtrl" class="col-md-6">
<strong>Applications</strong> <asp:button formnovalidate="formnovalidate" id="addApplication" style="cursor: pointer" class="btn-xs btn-primary" data-toggle="modal" data-target="#appModal">Add</asp:button>
<!-- AngularJS defined in wwwroot > js > sponsor-applications -->
<br />
<sponsor-applications></sponsor-applications>
</div>
</row>
</div>
<div class="col-md-12" style="margin-top:50px;">
<row>
<div class="col-md-2">
<input type="submit" value="Delete" disabled class="btn btn-default" />
</div>
<div class="col-md-offset-6 col-md-2" style="text-align:right">
<input type="submit" value="Save" class="btn btn-default" />
</div>
<div class="col-md-2">
<button class="btn btn-default" type="button" id="cancel" onclick="location.href='#Url.Action("Index", "Sponsors")'">Cancel</button>
</div>
</row>
</div>
</div>
</form>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
<!-- Modal to select delegates for sponsor -->
<div class="modal fade" tabindex="-1" role="dialog" id="delegatesModal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<strong>Please select the Delegates</strong>
<div id="delgates_tbl">
<!-- AngularJS defined in wwwroot > js > applications -->
<delegates></delegates>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn-sm btn-default no-modal" data-dismiss="modal" id="closeDelegate">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
Add Applications Button in Modal
<!-- Modal to select application for sponsor -->
<div class="modal fade" tabindex="-1" role="dialog" id="appModal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<strong>Please select the applications</strong>
<div id="divModalApps">
<!-- AngularJS defined in wwwroot > js > applications -->
<applications></applications>
</div>
</div>
<div class="modal-footer">
<button type="button"
ng-click="addApp('Cheese')"
class="btn-sm btn-default no-modal">
Add Applications
</button>
<button type="button" class="btn-sm btn-default no-modal"
data-dismiss="modal" id="closeApps">
Close
</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
----
the button HTML is on the Create.cshtml page, but so are all the templates aka
<sponsor-applications>
</sponsor-applications>
Also note that in the _Layouts.cshtml page all js files are referenced. ~/app.module.js, ~/app.config.js, ~/js/sponsor-delegates/sponsor-delegate.module.js, ~/js/sponsor-delegates/sponsor-delegates.component.js
sponsor-applications.component.js
//Author Robert B Dannelly
//Date 4/8/2019
//sponsor-applications
'use strict';
var testUrl = window.location.hostname;
if (testUrl.includes("localhost")) {
var apiUrl = 'https://localhost:44364';
}
else if (testUrl.includes("uat")) {
var apiUrl = 'https://localhost:44364'; //TODO when the URL is decided for UAT
}
else {
var apiUrl = 'https://localhost:44364'; //TODO when the URL is decided for PRD
}
// Register `sponsorApplications` component, along with its associated controller and template
angular.
module('App').
component('sponsorApplications', {
templateUrl: '../../js/sponsor-applications/sponsor-applications.template.html',
controller: ['$scope', '$http', function SponsorApplications($scope, $http) {
var user_id = $("#User_Id").val();
if (user_id != "") {
$http.get(apiUrl + '/api/v1/Sponsors/' + user_id + '/Applications').then(function successCallback(response) {
$scope.sponsorApplications = response.data;
console.log($scope.sponsorApplications);
}, function errorCallback() {
//var type = 'warning';
//var title = 'User Lookup Required!';
//var body = 'Please enter a User Login ID for lookup'
alert('Please try again later, network error, email sent to application administrator')
});
}
//TODO - Have to get rows from Modal to Page
// Add Rows
**********************BELOW is the correct SYNTAX********************
this.addApp = function (arg) {
alert(arg);
debugger;
console.log(arg);
};
//$scope.addApp = function (arg) {
// debugger;
// console.log(arg);
// alert(arg);
// //$scope.table.push($scope.newApp);
// // $scope.newApp = new Object();
//};
// Remove Rows
$scope.remove = function (index) {
debugger;
$scope.sponsorApplications.splice(index, 1);
};
}
]
});
Create.cshtml Changes
In the template
<div id="divMyAppCtrl" class="col-md-6">
<strong>Applications</strong> <asp:button formnovalidate="formnovalidate" id="addApplication" style="cursor: pointer" class="btn-xs btn-primary" data-toggle="modal" data-target="#appModal">Add</asp:button>
<!-- AngularJS defined in wwwroot > js > sponsor-applications -->
<br />
<sponsor-applications ng-ref="sponsorApplications"></sponsor-applications>
</div>
Add Applications Modal in the footer
<div class="modal-footer">
<button type="button" ng-click="sponsorApplications.addApp('CLicked')" class="btn-sm btn-default no-modal">Add Applications</button>
<button type="button" class="btn-sm btn-default no-modal" data-dismiss="modal" id="closeApps">Close</button>
</div>

Laravel modal hidden value to call route

I have a modal with a hidden field of my current id that I need.
I need to click a button in my modal to confirm if I should delete a user. I setup a form not sure if this is the best option and in javascript set the attr of form to the route but the route isn’t finding the correct path although in the URL it says it correctly what am I missing maybe the route should be in PHP instead of JS?
<div class="modal" id="mdelete" role="dialog" aria-labelledby="moddelete">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="moddelete">Confirm Delete</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete</p>
</div>
<div class="modal-footer">
<form method="POST" id="formdelete">
<input type="hidden" name="txtid" id="txtid" />
<input type="text" name="uid" id="uid" />
<button type="button" class="btn btn-danger " data-dismiss="modal">No</button>
<span class="text-right">
<button type="submit" class="btn btn-primary btndelete">Yes</button>
</span>
</form>
</div>
</div>
Show
Edit
<button type="button" class="btn btn-danger ml-2" data-toggle="modal"
data-target="#mdelete" data-id="{{$user->id}}"
data-name="{{$user->username}}">Delete</button>
$(document).ready(function() {
$('#mdelete').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
var userid = button.data('id');
var uname = button.data('name');
var modal = $(this);
modal.find('#txtid').val(userid);
modal.find('#uid').val(userid);
modal.find('.modal-body').text('Are you sure you want to delete ' + uname);
})
$('#formdelete').submit(function() {
var userid = $('#txtid').val();
$('#formdelete').attr("action", "route('$users.destroy',$user->"+ userid +")");
$('#formdelete').submit();
});
});
Your attempt to generate route will fail because you are not using templating correctly:
$('#formdelete').attr("action", "route('$users.destroy',$user->"+ userid +")");
You can try to have your route accept optional user field, and then generate route to it, and with js append user ID value something like so:
<script>
$(function() {
var form = $('#formdelete');
var path = '{{ route("users.destroy") }}';
$('#formdelete').submit(function(event) {
var form = $(this);
var userid = form.find('#txtid').val();
$('#formdelete').attr("action", path + '/' + userid);
$('#formdelete').submit();
});
});
</script>

Modal in asp.net view not working properly

In my strongly typed view I am looping over a list of objects coming from a database. Each of these objects is presented in a jumbotron, which has a button "Had role before". On click the modal opens and there I want to input some data in input boxes and save it to my database via an ajax call. One part of data that I want to input is the unique id which each object in the loop has. With the code I have so far I managed on click to get the id of the first object, but when I am clicking the buttons for the rest of the objects nothing happens.
This is the script in my view :
<script type="text/javascript">
$(document).ready(function () {
$(function () {
var idW;
$('#mdl').on('click', function () {
var parent = $(this).closest('.jumbotron');
var name = parent.find('input[name="mdlname"]').val();
var id = parent.find('input[name="mdlwrid"]').val();
var idW = id;
console.log(idW);
var titleLocation = $('#myModal').find('.modal-title');
titleLocation.text(name);
$('#myModal').modal('show');
});
});
$('#mdlSave').on('click', function () {
console.log('x');
addPastRoleAjax();
});
function addPastRoleAjax() {
$.ajax({
type: "POST",
url: '#Url.Action("addPastRole", "WorkRoles")',
dataType: "json",
data: {
wrId: idW,
dateStart: $("#wrdateStart").val(),
dateEnd: $("#wrknamedateEnd").val()
},
success: successFunc
});
function successFunc(data, status) {
if (data == false) {
$(".alert").show();
$('.btn').addClass('disabled');
//$(".btn").prop('disabled', true);
}
}
</script>
the loop :
#foreach (var item in Model)
{
<div class="jumbotron">
<input type="hidden" name="mdlwrid" value="#item.WorkRoleId" />
<input type="hidden" name="mdlname" value="#item.RoleName" />
<h1>#Html.DisplayFor(modelItem => item.RoleName)</h1>
<p class="lead">#Html.DisplayFor(modelItem => item.RoleDescription)</p>
<p> #Html.ActionLink("Focus on this one!", "addWorkRoleUser", new { id = item.WorkRoleId }, new { #class = "btn btn-primary btn-lg" })</p>
<p> <button type="button" id ="mdl" class="btn btn-default btn-lg" data-toggle="modal" data-target="#myModal">Had role in the past</button> </p>
</div>
}
The modal :
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title"></h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
<input id="wrdateStart" class='date-picker' />
<input id="wrknamedateEnd" class='date-picker' />
</div>
<div class="modal-footer">
<button type="button" id="mdlSave" class="btn btn-default" data-dismiss="modal">Save</button>
</div>
</div>
</div>
Your problem is in the following piece of code:
#foreach (var item in Model)
{
<div class="jumbotron">
<input type="hidden" name="mdlwrid" value="#item.WorkRoleId" />
<input type="hidden" name="mdlname" value="#item.RoleName" />
<h1>#Html.DisplayFor(modelItem => item.RoleName)</h1>
<p class="lead">#Html.DisplayFor(modelItem => item.RoleDescription)</p>
<p> #Html.ActionLink("Focus on this one!", "addWorkRoleUser", new { id = item.WorkRoleId }, new { #class = "btn btn-primary btn-lg" })</p>
<p> <button type="button" id ="mdl" class="btn btn-default btn-lg" data-toggle="modal" data-target="#myModal">Had role in the past</button> </p>
</div>
}
You have used a foreach loop and inside it you create button elements with same id.
<button type="button" id ="mdl" class="btn btn-default btn-lg" data-toggle="modal" data-target="#myModal">Had role in the past</button>
So,foreach let you to create many buttons with same id. That's wrong and that's why you get that behavior(only first button work).The solution: Use classes instead.

Compiling dynamically generated buttons in Angular

I'm trying to dynamically generate a button in Angular. On click, that button needs to call the deleteRow() function and pass in a username. The applicable username is successfully passed to the controller and the resulting button code appears to be properly generated. However, they button ends up passing undefined to the deleteRow() function. Is this a problem with how I'm using $compile?
validationApp.controller('usersController', function ($scope, $compile, $http, $timeout){
$(document).on("click", ".open-confirm-dialog", function () {
var username = $(this).data('id');
var btnHtml = '<button class="btn btn-danger" data-title="Delete" ng-click="deleteRow(' + username + ')">DELETE</button>';
var temp = $compile(btnHtml)($scope);
angular.element(document.getElementById('deleteButton-dynamic')).append(temp);
});
$scope.deleteRow = function(username){
alert(username); //This shows 'undefined' in the pop-up
var request = $http({
method: "post",
url: "scripts/delete.php",
data: { un: username },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
request.success(function() { });
location.reload();
};
HTML as follows:
<div class="row" ng-controller="usersController">
<div class="table-responsive col-md-12" ng-show="filteredItems > 0">
<table id="users" class="table table-bordred table-striped">
<thead>
<th ng-click="sort_by('username');">Username: <i class="glyphicon glyphicon-sort"></i></th>
<th ng-click="sort_by('submitted_info');">Submitted Info.: <i class="glyphicon glyphicon-sort"></i></th>
</thead>
<tbody>
<tr ng-repeat="data in filtered = (list | orderBy : predicate :reverse)">
<td>{{data.username}}</td>
<td>{{data.submitted_info}}</td>
<td></span></td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-12" ng-show="filteredItems == 0">
<div class="col-md-12">
<h4>No customers found</h4>
</div>
</div>
<div class="col-md-12" ng-show="filteredItems > 0">
<div pagination="" page="currentPage" on-select-page="setPage(page)" boundary-links="true" total-items="filteredItems" items-per-page="entryLimit" class="pagination-small" previous-text="«" next-text="»"></div>
</div>
<!-- Confirm Modal -->
<div id="confirmModal" user-id="" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="confirmModal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Confirm Delete</h4>
</div>
<div class="modal-body">
Are you sure you want to delete this user from the database?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<span id="deleteButton-dynamic"></span>
<!--Working HardCoded Button
<button class="btn btn-danger" data-title="Delete" ng-click="deleteRow('user1')">WorkingButton</button>
-->
</div>
</div>
</div>
</div>
Angular assumes the value passed to deleteRow is part of the expression, therefore it checks the scope for a key that matches the value of username. Change the ng-click expression by wrapping the concatenated username string in quotes. E. G. deleteRow(\''+ username + '\')
Suggest using a directive.
To do this you would need to do the following based on the code you gave:
define the directive javascript itself
// First define the directive controller
function dynamicButton ($scope, $http){
$scope.deleteRow = function(){
// here $scope.username is defined based on the value from the parent controller
};
});
// This registers the directive with angular
validationApp.directive(dynamicButton.name, function(){
return {
controller: dynamicButton.name,
restrict: 'E',
templateUrl: 'pathtoyourhtmlpartial',
scope: {
username: '='
}
}
}
Update the html, i.e. call the directive from the original controller and save the new partial for the button.
trigger the directive in your original controller. (e.g. $scope.buttonSwitchedOn), when that it true, angular will automatically load in and run your directive

Categories