I've got a search results page that lists the search criteria elements and allows the user to click an element to remove that search criteria.
The first time clicking one of the criteria elements to remove it, everything works as expected.
However, the second time a criteria element is removed, the first removed element comes back.
Search criteria: {topic: "abuse"}, {profession: "admin"}, {keywords: "animal"}
Now click the "topic" element to remove it, the results page now shows {profession: "admin"}, {keywords: "animal"}
Now click "keywords" to remove it, the page now incorrectly shows {topic: "abuse"}, {profession: "admin"}
The correct display at this point should be only a single tag {profession: "admin"}
SearchController.Results()
<HttpPost>
<NoCache>
Function Results(ByVal model As SearchCriteria) As ActionResult
Dim resultsModel As SearchResultsModel = New SearchResultsModel
Dim searchQuery As IQueryable(Of [Class]) = Nothing
Dim searchResults As List(Of [Class]) = Nothing
Dim categoryValueQuery As IQueryable(Of CourseCategoryValue) = Nothing
Dim query As IQueryable(Of [Class]) = Nothing
Dim queries As List(Of IQueryable(Of [Class])) = New List(Of IQueryable(Of [Class]))
model = RemoveCriteria(model)
model.RemovalCriteria = String.Empty
resultsModel.Criteria = model
Return View(resultsModel)
End Function
SearchController.RemoveCriteria()
<NonAction>
Function RemoveCriteria(ByVal model As SearchCriteria) As SearchCriteria
Dim result As SearchCriteria = ObjectMapper.Duplicate(model)
If Not String.IsNullOrEmpty(result.RemovalCriteria) Then
Select Case result.RemovalCriteria.ToLower.Trim
Case "title"
result.Title = String.Empty
Case "keywords"
result.Keywords = String.Empty
Case "healthtopic"
result.HealthTopic = String.Empty
Case "city"
result.City = String.Empty
Case "profession"
result.Profession = String.Empty
End Select
End If
Return result
End Function
Results.vbhtml
@Imports System.Reflection
@ModelType SearchResultsModel
@Code
ViewData("Title") = "Results"
Dim properties As List(Of PropertyInfo) = Model.Criteria.GetType.GetProperties.ToList
Dim names() As String = {"keywords", "healthtopic", "profession"}
End Code
<h2>Results</h2>
@If (Not Nothing Is Model) AndAlso (Not Nothing Is Model.Results) Then
@<h3>Displaying @Model.Results.Count of @Model.ResultCount classes</h3>
End If
@Using Html.BeginForm("Results", "Search", Nothing, FormMethod.Post, New With {.id = "removalForm"})
@Html.Hidden("RemovalCriteria", String.Empty, New With {.id = "removalCriteria"})
@<div>
<span style="font-weight: bold;">Search Criteria </span>
@For Each name As String In names
Dim prop As PropertyInfo = (From p In properties Where p.Name.ToLower = name Select p).FirstOrDefault
Dim value As Object = prop.GetValue(Model.Criteria)
If Not Nothing Is value Then
value = value.ToString
If Not String.IsNullOrEmpty(value) Then
@<span class="criteriaTag" title="click to remove" onclick="submitRemovalForm('@prop.Name');">@prop.Name<span class="criteriaValue">@value</span></span>
End If
End If
@Html.Hidden(prop.Name, value)
Next
</div>
End Using
<script type="text/javascript">
function submitRemovalForm(removeTag) {
$('#removalCriteria').val(removeTag);
$('#removalForm').submit();
}
</script>
So, any thoughts on why this could be happening?
I am going to take a stab at how your code works, and if right, think I have your issue. It appears that for each criteria, you are outputting them in a hidden field. When you click a field, it adds that value to the hidden removeTag field then submits the form. On submit, it will exclude that field from the search query. If that's correct, here is what is going on:
You are not removing the property hidden input in the actual form. The form HTML markup probably looks something like the following:
<form>
<input type="hidden" name="RemovalCriteria" value=""/>
<input type="hidden" name="topic" value="abuse"/>
<input type="hidden" name="profession" value="admin"/>
<input type="hidden" name="keywords" value="animal"/>
</form>
So when you submit, you get something like the following on your form submit:
{
RemovalCriteria: "abuse",
topic: "abuse",
profession: "admin",
keywords: "animal"
}
When you next click remove on the "admin" tag, your form submission would look like:
{
RemovalCriteria: "admin",
topic: "abuse",
profession: "admin",
keywords: "animal"
}
Thus, abuse will be added back in. To prevent a previously removed tag from coming back, you would need to actually remove the hidden input associated with it as well:
<script type="text/javascript">
function submitRemovalForm(removeTag) {
$('#removalCriteria').val(removeTag);
$('#removalForm').remove($("input[type='hidden'][name='" + removeTag + "']"));
$('#removalForm').submit();
}
</script>
Which should change your form markup to the following after clicking on the remove topic tag:
<form>
<input type="hidden" name="RemovalCriteria" value="abuse"/>
<input type="hidden" name="profession" value="admin"/>
<input type="hidden" name="keywords" value="animal"/>
</form>
As to how this would impact your search (missing a property/tag combo) you might have to work out, it might not have any affect. But that appears to be why a removed tag is coming back.