I am converting a form from knockout to vue 2 with an ASP.NET MVC 5 Controller for the back end. This is my first attempt using vue. When the user presses the + button, it adds a new row onto the form. The issue I'm having is submitting that to the back end. The old knockout code dynamically set the name attribute in the form elements to Quantities so the form array properly submits all of the data. I would like to do the same thing with vue but am having a a bit of trouble dynamically setting the name of each element dynamically. What would be the best way to do this in order to submit the form without having to rewrite the Controller signature? It should store the form array under the name Quantities.
Image:
HTML:
<div id="radios" v-for="(row,key) in order">
<div class="row">
<div class="col-md-3">
#Html.SmartLabel("systemType", "System Type", true, labelClass)
<label>
<input type="radio" value="#Model.WifiId" v-model="order[key].selectedSystemType" v-on:change="systemChanged(key)"> Wifi
</label>
<label>
<input type="radio" value="#Model.WirelessId" v-model="order[key].selectedSystemType" v-on:change="systemChanged(key)"> Wireless
</label>
<label>
<input type="radio" value="#Model.FiberId" v-model="order[key].selectedSystemType" v-on:change="systemChanged(key)"> Fiber
</label>
</div>
<div class="col-md-4">
#Html.SmartLabel("assetType", "Asset Type", true, labelClass)
<!--
https://stackoverflow.com/questions/43812817/how-to-set-optgroup-select-label-in-vue-js
-->
<select id="asset-type" name="" class="form-control" v-model="order[key].selectedAsset" v-on:change="assetTypeChanged(key)">
<optgroup v-for="(group, name) in order[key].assets" v-bind:label="name">
<option v-for="asset in group" v-bind:value="asset">
{{asset.Name}}
</option>
</optgroup>
</select>
</div>
<div class="col-md-2">
#Html.SmartLabel("quantity", "Quantity", true, labelClass)
<input type="number" min="1" class="form-control" v-model="order[key].quantity" />
</div>
<div class="col-md-2">
<div v-show="costTracked">
#Html.SmartLabel("cost", "Unit Cost", true, labelClass)
<input type="number" min="1" class="form-control" v-model="order[key].cost" />
</div>
</div>
<div>
<span style="cursor:pointer" v-on:click="removeItem(key)">
X
</span>
</div>
</div>
</div>
Vue.js code:
var app = new Vue({
el: '#vue-app',
data: {
assets: {},
assetQuantityEnabled: false,
costTracked: false,
order: []
//Quantities: []
},
methods: {
// Trigger when system type radio selection changes
systemChanged: function (key) {
$.getJSON('#Url.Action( "GetAssetsOfSystem", "RadioOrder" )?systemTypeId=' + this.order[key].selectedSystemType, function (data) {
var result = {};
// Add assets to category (AssetCategory)
for (const asset of data) {
(asset.AssetCategoryName in result) ? result[asset.AssetCategoryName].push(asset) : result[asset.AssetCategoryName] = [];
}
// Sort assets within each category
for (const option in result) {
result[option].sort((a, b) => {
return a.Name.localeCompare(b.Name);
});
}
this.order[key].assets = result;
this.costTracked = false;
this.assetQuantityEnabled = false;
}.bind(this));
},
assetTypeChanged: function (key) {
this.assetQuantityEnabled = true;
this.costTracked = this.hasMacOrSerial(this.order[key].selectedAsset);
},
addItem: function () {
obj = this.defaultObj();
this.order.push(obj);
},
convertFormData: function(){
var q = [];
for(let i=0; i < this.order.length; i++)
{
var obj = {
AssetTypeId: this.order[i].selectedAsset.AssetTypeId,
AssetTypeIsSerialized: this.hasMacOrSerial(this.order[i].selectedAsset),
Quantity: this.order[i].quantity,
UnitCost: this.order[i].cost
};
q.push(obj);
}
return q;
},
defaultObj: function () {
return {
asset: '',
assets: [], // list items
cost: 0,
quantity: 1,
selectedSystemType: null,
selectedAsset: null
};
},
hasMacOrSerial: function (asset) {
return (asset.HasMacAddress || asset.HasSerialNumber) ? true : false;
},
removeItem: function (key) {
this.order.splice(key, 1);
}
}
});
Controller method signature:
public virtual ActionResult Create(
[Bind(Include = "VendorId,OrderNumber,RequisitionNumber,Quantities,SerializedAssets,Attempt")] InventoryOrderDto dto)
Old HTML using Knockout:
<div class="col-md-6">
<div class="panel panel-default white-box">
<div class="panel-heading">
<h3 class="panel-title">Order Summary</h3>
</div>
<div class="panel-body">
<div id="radios" data-bind="foreach: QuantitiesDisplay, visible: QuantitiesDisplay().length > 0" style="display: none">
<div class="row">
<input type="hidden" data-bind="value: AssetTypeId, attr: {name: 'Quantities[' + $index() + '].AssetTypeId'}" />
<input type="hidden" data-bind="value: AssetTypeIsSerialized, attr: {name: 'QuantitiesDisplay[' + $index() + '].AssetTypeIsSerialized'}" />
<input type="hidden" data-bind="value: UnitCost, attr: {name: 'Quantities[' + $index() + '].UnitCost'}" />
<div class="col-md-3" data-bind="text: AssetTypeName" style=" word-break: break-all;">
</div>
<div class="col-md-3">
<input type="number" min="1" class="form-control" data-bind="value: Quantity, attr: {name: 'Quantities[' + $index() + '].Quantity'}" />
</div>
<div class="col-md-3">
<input type="number" min="1" class="form-control" data-bind="visible:AssetTypeIsSerialized, value: UnitCost, attr: {name: 'Quantities[' + $index() + '].UnitCost'}" />
</div>
<div class="col-md-2">
<a class="btn btn-danger" title="Remove" data-bind="click: $root.removeItem">
<i class="fa fa-minus-circle"></i> Remove
</a>
</div>
</div>
</div>
<div id="emptyOrder" data-bind="visible: QuantitiesDisplay().length == 0">
No items are currently selected. Please choose from the adjacent pane.
</div>
<input id="submit" type="submit" value="Continue" class="btn btn-primary" data-bind="visible: QuantitiesDisplay().length > 0" style="display: none">
</div>
</div>
</div>
Ah I found it - need to use v-bind to dynamically set the name.
<div class="col-md-2">
#Html.SmartLabel("quantity", "Quantity", true, labelClass)
<input type="number" min="1" class="form-control" v-model="order[key].quantity" v-bind:name="'Quantities[' + key + '].Quantity' " />
</div>
https://medium.com/swlh/building-dynamic-forms-with-django-formsets-and-vue-js-f3c6e2dddd4a
Related
I have Test and Deta(Details) table in DB. With Entity Framework 5 I have obtained a model so I have classes generated from it. I also created controllers and views for the Deta table. I can add, clear and delete the records before saving but finally, I can't to save the records.
Test table has
(TestID,
MissionCode,
StartDate,
EndDate)
Deta table has
(DetaId,
TestType,
TestDate,
Driver,
Place,
TestID)
I used the following script in the view to add, clear and save the record.
#section scripts{
<script>
//Show Modal.
function addNewDeta() {
$("#newDetaModal").modal();
}
//Add Multiple Order.
$("#addToList").click(function (e) {
e.preventDefault();
if ($.trim($("#testType").val()) == "" || $.trim($("#testDate").val()) == "" || $.trim($("#driver").val()) == "" || $.trim($("#place").val()) == "") return;
var testType = $("#testType").val(),
testDate = $("#testDate").val(),
driver = $("#driver").val(),
place = $("#place").val(),
detailsTableBody = $("#detailsTable tbody");
var tstItem = '<tr><td>' + testType + '</td><td>' + testDate + '</td><td>' + driver + '</td><td>' + place + '</td><td><a data-itemId="0" href="#" class="deleteItem">Remove</a></td></tr>';
detailsTableBody.append(tstItem);
clearItem();
});
//After Add A New Order In The List, Clear Clean The Form For Add More Order.
function clearItem() {
$("#testType").val('');
$("#testDate").val('');
$("#driver").val('');
$("#place").val('');
}
// After Add A New Order In The List, If You Want, You Can Remove It.
$(document).on('click', 'a.deleteItem', function (e) {
e.preventDefault();
var $self = $(this);
if ($(this).attr('data-itemId') == "0") {
$(this).parents('tr').css("background-color", "#ff6347").fadeOut(800, function () {
$(this).remove();
});
}
});
//After Click Save Button Pass All Data View To Controller For Save Database
function saveDeta(data) {
return $.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: 'POST',
url: "/Detas/SaveDeta",
data: data,
success: function (result) {
alert(result);
location.reload();
},
error: function () {
alert("Error!")
}
});
}
//Collect Multiple Order List For Pass To Controller
$("#saveDeta").click(function (e) {
e.preventDefault();
var detaArr = [];
detaArr.length = 0;
$.each($("#detailsTable tbody tr"), function () {
detaArr.push({
testType: $(this).find('td:eq(0)').html(),
testDate: $(this).find('td:eq(1)').html(),
driver: $(this).find('td:eq(2)').html(),
place: $(this).find('td:eq(3)').html()
});
});
var data = JSON.stringify({
missionCode: $("#missionCode").val(),
startDate: $("#startDate").val(),
endDate: $("#endDate").val(),
deta: detaArr
});
$.when(saveDeta(data)).then(function (response) {
console.log(response);
}).fail(function (err) {
console.log(err);
});
});
</script>
}
This is the controller
namespace WebApplication2.Controllers
{
public class DetasController : Controller
{
ETHADAMISEntities db = new ETHADAMISEntities();
public ActionResult Index()
{
List<Test> DetaAndTest = db.Tests.ToList();
return View(DetaAndTest);
}
public ActionResult SaveDeta(string missionCode, DateTime startDate, DateTime endDate, Deta[] deta)
{
string result = "Error! Test Detail Is Not Complete!";
if (missionCode != null && startDate != null && endDate != null && deta != null)
{
var tstId = Guid.NewGuid();
Test model = new Test
{
TestID = tstId,
MissionCode = missionCode,
StartDate = startDate,
EndDate = endDate
};
db.Tests.Add(model);
foreach (var item in deta)
{
var id = Guid.NewGuid();
Deta O = new Deta
{
DetaId = id,
TestType = item.TestType,
TestDate = item.TestDate,
Driver = item.Driver,
Place = item.Place,
TestID = tstId
};
db.Detas.Add(O);
}
db.SaveChanges();
result = "Success! Test with Detail Is Complete!";
}
return Json(result, JsonRequestBehavior.AllowGet);
}
}
}
This is the view
#model IEnumerable<WebApplication2.Models.Test>
<br /><br />
<div class="panel panel-default">
<div class="panel-heading">
<div class="row">
<h2 class="panel-title pull-left" style="margin-left:10px;">
<strong>Test Details</strong>
</h2>
<button style="margin-right:10px" class="btn btn-primary pull-right" onclick="addNewDeta()">New Test</button>
</div>
</div>
#*Receive All Database Data From Controller And Display Those Data In Client Side*#
#if (Model.Count() != 0)
{
foreach (var item in Model)
{
<div class="panel-body">
<table class="table table-striped table-responsive">
<tbody>
<tr>
<td>Mission Code : #item.MissionCode </td>
<td>Start Date : #item.StartDate </td>
<td>End Date : #item.EndDate</td>
</tr>
<tr>
<td colspan="3">
<table class="table table-bordered">
<tbody>
<tr>
<th>Test Type</th>
<th>Test Date</th>
<th>Driver</th>
<th>Place</th>
</tr>
#foreach (var deta in item.Detas)
{
<tr>
<td>#deta.TestType</td>
<td>#deta.TestDate</td>
<td>#deta.Driver</td>
<td>#deta.Place</td>
</tr>
}
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
}
}
else
{
<div class="panel-body">
<h3 style="color:red;">Empty!</h3>
</div>
}
</div>
#*Desing Bootstrap Modal With Order Form*#
<div class="modal fade" id="newDetaModal">
<div class="modal-dialog modal-lg" style=" width: 900px !important;">
<div class="modal-content">
<div class="modal-header">
×
<h4>Add New Test</h4>
</div>
<form id="NewDetailForm">
<div class="modal-body">
#*Test Details*#
<h5 style="color:#ff6347">Tests</h5>
<hr />
<div class="form-horizontal">
<input type="hidden" id="TestID" />
<div class="form-group">
<label class="control-label col-md-2">
Mission Code
</label>
<div class="col-md-4">
<input type="text" id="missionCode" name="missionCode" placeholder="Mission Code" class="form-control" />
</div>
<label class="control-label col-md-2">
Start Date
</label>
<div class="col-md-4">
<input type="text" id="startDate" name="startDate" placeholder="Start Date" class="form-control" />
</div>
<label class="control-label col-md-2">
End Date
</label>
<div class="col-md-4">
<input type="text" id="endDate" name="endDate" placeholder="End Date" class="form-control" />
</div>
</div>
</div>
#*Test Detail Details*#
<h5 style="margin-top:10px;color:#ff6347">Test Details</h5>
<hr />
<div class="form-horizontal">
<input type="hidden" id="DetaId" />
<div class="form-group">
<label class="control-label col-md-2">
Test Type
</label>
<div class="col-md-4">
<input type="text" id="testType" name="testType" placeholder="Test Type" class="form-control" />
</div>
<label class="control-label col-md-2">
Test Date
</label>
<div class="col-md-4">
<input type="datetime" id="testDate" name="testDate" placeholder="Test Date" class="form-control" />
</div>
<label class="control-label col-md-2">
Place
</label>
<div class="col-md-4">
<input type="text" id="place" name="place" placeholder="Place" class="form-control" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">
Driver
</label>
<div class="col-md-4">
<input type="text" id="driver" name="driver" placeholder="Driver" class="form-control" />
</div>
<div class="col-md-2 col-lg-offset-4">
<a id="addToList" class="btn btn-primary">AddToList</a>
</div>
</div>
<table id="detailsTable" class="table">
<thead>
<tr>
<th style="width:30%">Test Type</th>
<th style="width:20%">Test Date</th>
<th style="width:25%">Driver</th>
<th style="width:15%">Place</th>
<th style="width:10%"></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="reset" class="btn btn-default" data-dismiss="modal">Close</button>
<button id="saveDeta" type="submit" class="btn btn-success">Save Test Detail</button>
</div>
</form>
</div>
</div>
</div>
I am working on a registration form. I want to show and hide my users past registrations using a button.The button should only show or hide registrations that are gone not the upcoming ones This is what I have so far. Pleasssseeee Help.
<div class="Table01">
<button id="older">Show Registration History</button>
#foreach (var sm in Model)
{
var tmp = #sm.SeminarNm.Replace("&", "and");
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 well table-item" align="left" data-toggle="tooltip" data-eventtype="#tmp" data-placement="top" title="#tmp">
<span class="sortName mid-weight"> #sm.SeminarNm</span>
<span class="sortDate alert-info">(ON #string.Format("{0:yyyy-MM-dd}", #sm.SessionStartDT) IN #sm.SessionCityNm)</span>
<div class="row " style="margin-top:10px">
#if (#sm.IsEditable == "Y")
{
using (Html.BeginForm("EditRegister", "App", FormMethod.Post, new { onclick = "showPageLoadingSpinner()" }))
{ #Html.AntiForgeryToken()
<div class="col-xs-12 col-md-6 col-lg-6">
<input class="btn btn-success " name="submitButton" type="submit" value="Edit" />
<input type="hidden" value="#sm.RegistrantSeq" name="hiddenseq" />
<input type="hidden" value="0" name="cntView" />
<input type="hidden" value="EditRegister" name="cntStage" />
</div>
}
}
#using (Html.BeginForm("ViewRegister", "App", FormMethod.Post))
{ #Html.AntiForgeryToken()
<div class="col-xs-12 col-md-6 col-lg-6 col">
<input class="btn btn-info" name="submitButton" type="submit" value="View" />
<input type="hidden" value="#sm.RegistrantSeq" name="hiddenseq" />
<input type="hidden" value="ViewRegister" name="cntStage" />
</div>
}
//
</div>
}
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
<script>
var $btns = $('.btn').click(function () {
if (this.id == 'older') {
$('#child > div').toggle(450);
}
$btns.removeClass('active');
$(this).addClass('active');
})
</script>
My Program Pic
I dont know if I need some sorting javascript function to display only those sessions that are in the past. Nothing seems to be working.
Assuming old registrations are any item with SessionStartDT value earlier than current date, you can set an html data attribute on each item's container div indicating whether it is an old item or new item and when user clicks the hide/show button, toggle the visibility of these items.
#foreach (var sm in Model)
{
<div data-old="#(p.SessionStartDT.Date < DateTime.Today.Date)">
<!-- your existing code for rendering each item goes here -->
</div>
}
And in the javascript part, when the button is clicked, make select the elements who's data-old attribute value is True (which we set via our C# expression which results in a boolean value) and toggle the visibility.
$(document).ready(function() {
$("#older").click(function(e) {
e.preventDefault();
$("[data-old='True']").toggle();
});
});
I want to add a project name and task name while clicking on a particular date in fullcalendar but I don't know how to use bootbox.prompt or bootbox.dialog with more than one fields so can you help me out?
select: function (start, end, allDay) {
debugger;
bootbox.prompt("Add New Event", function (title) {
debugger;
if (title !== null) {
calendar.fullCalendar('renderEvent',
{
title: title,
start: start,
end: end,
allDay: allDay,
className: 'label-info'
},
true // make the event "stick"
);
}
});
It's quite simple, we can use bootbox dialog for that
bootbox.dialog({
title: 'Add New Event',
message: $('#form'),
show: false,
}).on("shown.bs.modal", function (e) {
$('#form').show()
}).on('hide.bs.modal', function (e) {
/**
* Bootbox will remove the modal (including the body which contains the login form)
* after hiding the modal
* Therefor, we need to backup the form
*/
$('#form').hide().appendTo('body');
})
.modal('show');
calendar.fullCalendar('unselect');
}
In html
<form id="form" method="post" class="form-horizontal" style="display: none;">
<div class="form-group">
<label class="col-xs-3 control-label">Username</label>
<div class="col-xs-5">
<input type="text" class="form-control" name="username" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Password</label>
<div class="col-xs-5">
<input type="password" class="form-control" name="password" />
</div>
</div>
<div class="form-group">
<div class="col-xs-5 col-xs-offset-3">
<button type="submit" class="btn btn-primary" style="float:right;">Login</button>
</div>
</div>
Im using Mvc with Angularjs here I am fetching data from Database using join and Display data in table when i click on Edit button that particular row is binding in Bootstrap "modal" but why country,State Names not binding in the dropdown.
Here i'm showing Linq query:
public JsonResult GetAssData()
{
var x = (from n in db.Accessors
join ctr in db.Countrys on n.CountryID equals ctr.CountryID
join sts in db.States on n.StateID equals sts.StateID
select new { n.Id, n.Name, n.Email, n.Password, n.GEnder, n.Active, ctr.CountryName, sts.StateName, });
return new JsonResult { Data = x, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
public JsonResult EditSer(int id = 0)
{
var x = (from n in db.Accessors
where n.Id == id
join ctr in db.Countrys on n.CountryID equals ctr.CountryID
join sts in db.States on n.StateID equals sts.StateID
select new
{
n.Id,
n.Name,
n.Email,
n.Password,
n.GEnder,
ctr.CountryName,
sts.StateName,
});
return new JsonResult { Data = x, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
public JsonResult BindCtry()
{
var x = from n in db.Countrys select n;
return new JsonResult { Data = x, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
public JsonResult BindStates(int Id = 0)
{
var x = from n in db.States
where n.CountryID == Id
select n;
return new JsonResult { Data = x, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
AngularJs
app.controller('MyBindCNtrls', function ($scope, MyBindServiceservice) {
GetAssusData();
function GetAssusData() {
var xxx = MyBindServiceservice.getAss();
xxx.then(function (d) {
$scope.access = d.data;
})
}
$scope.EditEmp = function (Emp) {
alert('in EditModes')
var sss = MyBindServiceservice.EditAssFun(Emp.Id);
sss.then(function (d) {
$scope.Id = Emp.Id;
$scope.Name = Emp.Name;
$scope.GEnder = Emp.GEnder;
$scope.Email = Emp.Email;
$scope.Password = Emp.Password;
$scope.CountryID = Emp.CountryID;
$scope.CountryName = Emp.CountryName;
$scope.StateName = Emp.StateName;
$scope.ValidAction = 'Update';
$('#Modalpopup').modal('show');
})
}
})
app.service('MyBindServiceservice', function ($http) {
this.getAss = function () {
var xx = $http({
url: '/Bindctrl/GetAssData',
method: 'Get',
params: JSON.stringify(),
content: { 'content-type': 'application/Json' }
})
return xx;
}
this.EditAssFun = function (Id) {
alert('enter in edit ser')
var sts = $http({
url: '/Bindctrl/EditSer',
method: 'Get',
params: {
Id: JSON.stringify(Id)
}
});
return sts;
}
});
<div ng-controller="MyBindCNtrls">
<table class="table table-bordered">
<tr>
<th><b>Id</b></th>
<th><b>Name</b></th>
<th><b>Email</b></th>
<th><b>Password</b></th>
<th><b>Gender</b></th>
<th><b>CountryName</b></th>
<th><b>StateName</b></th>
<th><b>Action</b></th>
</tr>
<tr ng-repeat="Accessor in access">
<td>{{Accessor.Id}}</td>
<td>{{Accessor.Name}}</td>
<td>{{Accessor.Email}}</td>
<td>{{Accessor.Password}}</td>
<td>{{Accessor.GEnder}}</td>
<td>{{Accessor.CountryName}}</td>
<td>{{Accessor.StateName}}</td>
<td>
<button type="button" class="btn btn-success btn-sm" value="Edit" ng-click="EditEmp(Accessor)"><span class="glyphicon glyphicon-pencil"></span></button>
</td>
</tr>
</table>
<div class="modal" id="Modalpopup">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button class="close" data-dismiss="modal">×</button>
<h3>{{msg}}Login Details</h3>
</div>
<div class="modal-body">
<form novalidate name="f1" ng-submit="SaveDb(Ass)">
<div>
{{Errormsg}}
</div>
<div class="form-horizontal">
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
Name
</div>
<div class="col-sm-8">
<input type="text" class="form-control" name="nam" ng-model="Name" ng-class="Submittes?'ng-dirty':''" required autofocus />
<span class="Error" ng-show="(f1.nam.$dirty || Submittes) && f1.nam.$error.required">Enter Name</span>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
Email
</div>
<div class="col-sm-8">
<input type="text" class="form-control" name="MailId" ng-model="Email" ng-class="Submittes?'ng-dirty':''" required />
<span class="Error" ng-show="(f1.MailId.$dirty || Submittes) && f1.MailId.$error.required">Enter Email</span>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
Password
</div>
<div class="col-sm-8">
<input type="text" name="psw" class="form-control" ng-model="Password" ng-class="Submittes?'ng-dirty':''" required />
<span class="Error" ng-show="(f1.psw.$dirty || Submittes) && f1.psw.$error.required">Enter Password</span>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
Gender
</div>
<div class="col-sm-8">
<input type="radio" value="Male" name="Gen" ng-model="GEnder" ng-class="Submittes?'ng-dirty':''" required />Male
<input type="radio" value="Fe-Male" name="Gen" ng-model="GEnder" ng-class="Submittes?'ng-dirty':''" required />Fe-Male
<br />
<span class="Error" ng-show="(f1.Gen.$dirty || Submittes) && f1.Gen.$error.required">Select Gender</span>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
Country
</div>
<div class="col-sm-8">
<select class="form-control" name="cntrsy" ng-options="I.CountryID as I.CountryName for I in CountryList" ng-model="CountryID" ng-change="GetStates()" ng-class="Submittes?'ng-dirty':''" required>
<option value="">Select Country</option>
</select>
<span class="Error" ng-show="(f1.cntrsy.$dirty || Submittes) && f1.cntrsy.$error.required">Select Country</span>
{{CountryName}}
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
StateName
</div>
<div class="col-sm-8">
<select class="form-control" name="sts" ng-options="I.StateID as I.StateName for I in StateList" ng-model="StateID" ng-change="GetCitys()" ng-class="Submittes?'ng-dirty':''" required>
<option value="">Select Country</option>
</select>
<span class="Error" ng-show="(f1.sts.$dirty || Submittes) && f1.sts.$error.required">Select States</span>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-sm btn-success pull-right" value="{{ValidAction}}" ng-class="SaveAndSubmit()" />
#* <input type="button" class="btn btn-sm pull-right" value="Cancel" id="BtnCancel" />*#
</div>
</form>
</div>
</div>
</div>
</div>
</div>
I made a custom HTML helper for the contact modal so that anyone on our app can use it with #Html.ContactModal(model and options go here), but the issue is that on the modal there's another html helper for the sales code drop down, and the razor isn't rendering correctly. I tried to do everything with a partial view only to learn you can't (or shouldn't) use partials with html helpers, only with controllers (I'm new to all of this...), a co-worker suggested I use a tag builder, but I wanted to ask here first before writing the entire form with a tag builder.
public static IHtmlString ContactModal(this HtmlHelper htmlHelper, ContactModalOptions options)
{
//required scripts
htmlHelper.AddScriptFile("~/Areas/Customers/Scripts/ContactModal/tmi.customers.contactModal.js");
htmlHelper.AddScriptLine("$('#" + options.controlId + "').contactModal(" + options.ToJson() + ");", true);
string htmlContents = string.Empty;
htmlContents = $#"<div id='contactModalContainer' style='display: none'>
<div class='panel panel-default panel-details' id='' style='display: none'>
<div class='panel-heading' id='divContactModalHeading'>
<h3 id='h3contactModalHeading'></h3>
</div>
<div class='panel-body' id='divContactDetBody'>
<form id='custContactDetailsForm'>
<div class='row'>
<div class='col-sm-6'>
<div class='form-group' style=''>
<label for='txtFirstName' id='lblFirstName' class='control-label'>First Name: </label>
<input data-helper='FirstName' id='contactFirstName' type='text' class='form-control' disabled='disabled' data-editable='true' value='' />
</div>
</div>
<div class='col-sm-6'>
<div class='form-group' style=''>
<label for='txtLastName' class='control-label'>Last Name: </label>
<input data-helper='LastName' id='contactLastName' type='text' class='form-control' disabled='disabled' data-editable='true' value='' />
</div>
</div>
<div class='col-md-12'>
<div class='form-group' style=''>
<label for='txtPositionTitle'>Position/Title: </label>
<input id='contactPosition' data-helper='Position' type='text' class='form-control' disabled='disabled' data-editable='true' value='' />
</div>
</div>
<div class='col-md-12'>
<div class='form-group' style=''>
<label for='txtSalesOrders'>E-mail: </label>
<input id='contactEmail' data-helper='Email' type='text' class='form-control' disabled='disabled' data-editable='true' value='' />
</div>
</div>
<div class='col-sm-4'>
<div class='form-group' style=''>
<label for='txtSalesOrders'>Work Phone: </label>
<input id='contactWorkPhone' data-helper='DirectPhone' type='text' class='form-control' disabled='disabled' data-editable='true' value='' />
</div>
</div>
<div class='col-sm-4'>
<div class='form-group' style=''>
<label for='txtMobilePhone'>Mobile Phone: </label>
<input id='contactMobile' data-helper='MobilePhone' type='text' class='form-control' disabled='disabled' data-editable='true' value='' />
</div>
</div>
<div class='col-sm-4'>
<div class='form-group' style=''>
<label for='txtFax'>Fax: </label>
<input id='contactFax' data-helper='Fax' type='text' class='form-control' disabled='disabled' data-editable='true' value='' />
</div>
</div>
<div class='col-sm-4'>
<div class='form-group' style=''>
<label for='txtHomePhone'>Home Phone: </label>
<input id='contactHomePh' data-helper='HomePhone' type='text' class='form-control' disabled='disabled' data-editable='true' value='' />
</div>
</div>
<div class='col-sm-4'>
<div class='form-group' style=''>
<label for='txtPager'>Other Phone: </label>
<input id='contactPager' data-helper='PagerPhone' type='text' class='form-control' disabled='disabled' data-editable='true' value='' />
</div>
</div>
<div class='col-sm-12'>
<div class='form-group'>
<label for='txtNotes'>Notes/Comments: </label>
<textarea id='contactNotes' data-helper='ContactNotes' type='text' class='form-control' disabled='disabled' rows='3' data-editable='true' value=''></textarea>
</div>
</div>
<div class='col-sm-6'>
<div class='form-group' style=''>
<label for='txtDateAdded'>Date Added: </label>
<label id='contactDateAdded'></label>
</div>
</div>
<div class='col-sm-6' style='clear: both'>
<div class='form-group'>
<label class='control-label'>Referred By:</label>
<div class=''>
##Html.SalesCodeDropDown(new SelectControlOptionsBase('contactReferredBy')
{{
includeNull = true,isEditable = editableOptions.yes,
disabled = true,
}})
</ div >
</ div >
</ div >
< div class='col-md-6' style='clear: both'>
<div class='form-group' style=''>
<label for='txtEnteredBy'>Entered By: </label>
<label id = 'contactEnteredBy' ></ label >
</ div >
</ div >
< div class='col-md-6' style='clear: both'>
<div class='checkbox'>
<label>
<input id = 'contactIsInactiveChkBx' data-helper='Inactive' type='checkbox' disabled data-editable='true' value='0'>Inactive
</label>
</div>
</div>
</div>
</form>
</div>
</div>
<div id = 'contactModalFooter' class='form-group' style=''>
<button type = 'button' id='btnContactModalClose' style='margin-right: 5px;' class='pull-right btn btn-form-state'>Close</button>
<button type = 'button' id='btnContactModalCancel' style='margin-right: 5px;' class='pull-right btn btn-form-state'>Cancel</button>
<button type = 'button' id='btnContactModalSave' style='background-color: #EE6723; margin-right: 5px;' class='pull-right btn btn-form-state'>Save</button>
</div>
</div> ";
return MvcHtmlString.Create(htmlContents);
This ended up working:
public static IHtmlString ContactModal(this HtmlHelper htmlHelper, ContactModalOptions options)
{
StringBuilder result = new StringBuilder();
//required scripts
htmlHelper.AddScriptFile("~/Areas/Customers/Scripts/ContactModal/tmi.customers.contactModal.js");
htmlHelper.AddScriptLine("$('#" + options.controlId + "').contactModal(" + options.ToJson() + ");", true);
var body = htmlHelper.Partial("~/Areas/Customers/Views/Contacts/Shared/ContactModalPartial.cshtml").ToHtmlString();
result.AppendLine(body);
return MvcHtmlString.Create(result.ToString());
}
If your #Html.SalesCodeDropDown(new SelectControlOptionsBase('contactReferredBy') returns html, then just call that before you set the variable htmlContents and then concat it where you need to.