Business Logic
I have a company referral form, and in that form I have dropdown to select from a company list. But when a company is not found in the dropdown, the user can select option as "others", upon which a textbox will appear. Now the user can add the company in the textbox and will fill rest of the "referral form". Once the form is submitted, it will add that "new company" added by the user in my company list table so that from next time that company option is available in the dropdown. Also, I have a cover letter tied to all the companies. As soon as the user selects a company from the dropdown, I make an Ajax call to fetch the cover letters for that particular company.
Model
public class ReferralViewModel
{
public int Id { get; set; }
public bool IsResumeExists { get; set; }
public bool IsCoverLetterExists { get; set; }
// ********* Issue No 1 ************
[RequiredIf("CompanyId", "4", ErrorMessage = "Enter Company Name")]
[Display(Name = "Other Company")]
public string TempCompany { get; set; }
[Display(Name = "Resume")]
[Required]
public int ResumeId { get; set; }
public IEnumerable<SelectListItem> Resumes { get; set; }
// preventing from underposting attack
[Display(Name = "Company Name")]
[Required]
public int? CompanyId { get; set; }
public IEnumerable<SelectListItem> Companies { get; set; }
// needs to have "?" because when no dropdown is selected we want to pass NULL values
// question marks makes sure no default value is set by the framework.
[Display(Name = "Cover Letter")]
public int? CoverLetterId { get; set; }
public IEnumerable<SelectListItem> CoverLetters { get; set; }
}
View
@model Bridge.ViewModels.ReferralViewModel
@{
ViewBag.Title = "Create";
}
@using (Html.BeginForm("AddReferral",null,FormMethod.Post, new { id = "referralform", data_url = Url.Action("CheckForExistingReferral", "Referral") }))
{
@Html.AntiForgeryToken()
if (!Model.IsResumeExists)
{
<div class="alert alert-info">
<strong>No Resume Found!</strong> Click on <u><strong>@Html.ActionLink("Resume Center", "ResumeCenter", "Resume")</strong></u> and upload your Resume first.
</div>
}
else
{
<div class="form-horizontal">
<h4>Job Request</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.CompanyId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(m => m.CompanyId, Model.Companies, "Please Select", new { @class = "form-control", data_url = Url.Action("ListOfCoverLetterByCompanyId", "Referral") })
@Html.ValidationMessageFor(model => model.CompanyId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group js-div" style="display:none;">
@Html.LabelFor(model => model.TempCompany, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.TempCompany, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.TempCompany, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ResumeId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(m => m.ResumeId, Model.Resumes, "Please Select", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.ResumeId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CoverLetterId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(m => m.CoverLetterId, Model.CoverLetters, "Please select", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.CoverLetterId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
}
Script
$(function () {
var coverLetterSelect = $('#CoverLetterId');
$('#CompanyId').change(function () {
var companyId = $(this).val();
var url = $(this).data('url');
coverLetterSelect.empty();
if (!companyId) {
return;
}
// ********* Issue No 2 ************
if (companyId == 4)
{
$('.js-div').show();
}
else {
$('.js-div').hide();
}
// ********* Issue No 3 ************
$.ajax({
url: url,
type: 'POST',
data: { companyId: companyId },
success: function (response) {
coverLetterSelect.append($('<option></option>').val('').text('None'));
$.each(response, function (i, data) {
coverLetterSelect.append($('<option></option>').val(data.Value).text(data.Text));
});
},
error: function () { }
});
});
})
Controller Action
[HttpPost]
public JsonResult ListOfCoverLetterByCompanyId(int companyId)
{
var coverletters = _context.CoverLetters
.Where(c => c.CompanyId == companyId).Select(c => new
{
Value = c.CoverLetterId.ToString(),
Text = c.CoverLetterName
});
return Json(coverletters);
}
Issue: All these issue have also been marked in code. Scroll to the code to find them.
My foolproof plug's
REQUIREDIF
is based on the fact that Option 4. Whenever selected, that means the user is going to add a new company, which is working well in my local environment but will not work in a live app.In JavaScript I am checking again for "Option 4" and showing the user a temporary textbox for adding a new company dropdown option.
Unnecessary Ajax call even when the user has selected "others". We are sure when the user is selecting others as company then there will be no cover letter for it, so no need to make an Ajax call.
Basically, I have hardcoded in the database "Option 4" as a company named "others", but I think that is a bad approach. When I publish the app to live, that Option 4 will not be there.
Please help me with adding "others" in the dropdown in an elegant way. Also, note that I explicitly want to follow showing a textbox to add a company approach.