I am trying to understand the factory pattern where the factory takes a MeetingPollingQuestionType and returns the UI/MVC appropriate for the question type. I created this interface MeetingQuestionInterface
and one class LongAnswerText
that has a label
and TextBox
. When I run the program how do I send the view to the factory?
I am not sure how to pass in the
MeetingPollingQuestionType
and get this data populated? Should the interface take inMeetingPollingQuestionType
? Any help would be great.
Goal
the factory takes a MeetingPollingQuestionType and returns the UI/MVC appropriate for the question type.
JSON Data
[
{
"MeetingPollingQuestionId": 2,
"MeetingPollingQuestionType": "LongAnswerText",
"MeetingPollingId": 3,
"SequenceOrder": 1,
"MeetingPollingParts": [
{
"MeetingPollingPartsId": 2,
"Type": "Question",
"MeetingPollingQuestionId": 2,
"MeetingPollingPartsValues": [
{
"Type": "label",
"QuestionValue": "This is a long question",
"FileManagerId": 0,
"FileName": null,
"FileData": null,
"FileType": null
}
]
}
]
},
{
"MeetingPollingQuestionId": 3,
"MeetingPollingQuestionType": "MultipleChoice",
"MeetingPollingId": 3,
"SequenceOrder": 2,
"MeetingPollingParts": [
{
"MeetingPollingPartsId": 3,
"Type": "Question",
"MeetingPollingQuestionId": 3,
"MeetingPollingPartsValues": [
{
"Type": "label",
"QuestionValue": "this is a multiple choice question",
"FileManagerId": 0,
"FileName": null,
"FileData": null,
"FileType": null
}
]
},
{
"MeetingPollingPartsId": 4,
"Type": "Image",
"MeetingPollingQuestionId": 3,
"MeetingPollingPartsValues": [
{
"Type": "Image",
"QuestionValue": null,
"FileManagerId": 14552,
"FileName": null,
"FileData": null,
"FileType": null
}
]
},
{
"MeetingPollingPartsId": 5,
"Type": "Answers",
"MeetingPollingQuestionId": 3,
"MeetingPollingPartsValues": [
{
"Type": "radio",
"QuestionValue": "Yes",
"FileManagerId": 0,
"FileName": null,
"FileData": null,
"FileType": null
},
{
"Type": "radio",
"QuestionValue": "No",
"FileManagerId": 0,
"FileName": null,
"FileData": null,
"FileType": null
},
{
"Type": "radio",
"QuestionValue": "Abstain",
"FileManagerId": 0,
"FileName": null,
"FileData": null,
"FileType": null
}
]
}
]
}
]
Program
static void Main(string[] args)
{
LongAnswerText LongAnswerTextParts = new LongAnswerText();
var control = LongAnswerTextParts ()
}
interface MeetingQuestionInterface
{
string Label(string target, string text);
}
public class LongAnswerText : MeetingQuestionInterface
{
public static string Label(string target, string text)
{
return String.Format("<label for='{0}'>{1}</label>", target, text);
}
public static string TextBox(string target, string text)
{
return String.Format("<input for='{0}'>{1}</input>", target, text);
}
}
MVC form view
<div class="form-group">
@Html.LabelFor(c => c.LongAnswerText)
@Html.TextBoxFor(c => c.LongAnswerText, new { @class = "form-control" })
</div>
Sample
https://dotnetfiddle.net/j6YIPN
So I built a small example component for this use case, which I think works here, but depending on the data model might be optimized a bit more.
This is the actual component doing the strategising, so I called it StrategyComponent:
@switch (Input.Type)
{
case "label":
<label for="@id">@Input.QuestionValue</label>
break;
case "text":
<input id="@id" type="text"/>
break;
}
@code {
[Parameter]
public MeetingPollingPartsValues Input { get; set; } = null!;
private readonly Guid id = Guid.NewGuid(); // Because I'm not sure where to take the ID from
}
Then to use it you just do this:
@foreach (var value in Values)
{
<StrategyComponent Input="value" />
}
@code {
List<MeetingPollingPartsValues> Values { get; set; } = new(); // Put real data here
}
I hope I got the data model right, I just copied it from your fiddle. For the things around that it seems there is another model that also has its own type, I guess you can use the same pattern there.