Example #1
0
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            if (!isVisible)
            {
                output.SuppressOutput();
                return;
            }
            #region << Init >>
            var initSuccess = InitField(context, output);

            if (!initSuccess)
            {
                return;
            }

            if (Options == null)
            {
                Options = new List <WvSelectOption>();
            }

            if (Options.Count == 0 && AjaxDatasource != null && AjaxDatasource.InitOptions.Count > 0)
            {
                Options = AjaxDatasource.InitOptions;
            }

            if (AjaxDatasource != null && String.IsNullOrWhiteSpace(AjaxDatasourceApi))
            {
                if (!AjaxDatasource.UseSelectApi)
                {
                    //old fashion call
                    AjaxDatasourceApi = "/api/v3/en_US/eql-ds";
                }
                else
                {
                    //The new api
                    AjaxDatasourceApi = "/api/v3/en_US/eql-ds-select2";
                }
            }

            #region << Init Prepend and Append >>
            var content = await output.GetChildContentAsync();

            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(content.GetContent());
            var prependTaghelper = htmlDoc.DocumentNode.Descendants("wv-field-prepend");
            var appendTagHelper  = htmlDoc.DocumentNode.Descendants("wv-field-append");

            foreach (var node in prependTaghelper)
            {
                PrependHtml.Add(node.InnerHtml.ToString());
            }

            foreach (var node in appendTagHelper)
            {
                AppendHtml.Add(node.InnerHtml.ToString());
            }

            #endregion


            #region << Validate Options >>
            if (Options == null)
            {
                var divEl = new TagBuilder("div");
                divEl.AddCssClass("form-control-plaintext erp-plain-text");

                var errorListEl = new TagBuilder("ul");
                errorListEl.AddCssClass("erp-error-list list-unstyled");

                var errorEl = new TagBuilder("li");
                errorEl.AddCssClass("go-red");

                var iconEl = new TagBuilder("span");
                iconEl.AddCssClass("fa fa-fw fa-exclamation");

                errorEl.InnerHtml.AppendHtml(iconEl);
                errorEl.InnerHtml.Append($"Error:Select options cannot be null");

                errorListEl.InnerHtml.AppendHtml(errorEl);
                divEl.InnerHtml.AppendHtml(errorListEl);
                output.Content.AppendHtml(divEl);
                //Finally
                if (SubInputEl != null)
                {
                    output.PostContent.AppendHtml(SubInputEl);
                }
                return;
            }
            #endregion

            #endregion

            #region << Render >>
            if (Mode == WvFieldRenderMode.Form)
            {
                if (Access == WvFieldAccess.Full || Access == WvFieldAccess.FullAndCreate)
                {
                    var inputGroupEl = new TagBuilder("div");
                    inputGroupEl.AddCssClass("input-group");
                    //Prepend
                    if (PrependHtml.Count > 0)
                    {
                        var prependEl = new TagBuilder("span");
                        prependEl.AddCssClass($"input-group-prepend {(ValidationErrors.Count > 0 ? "is-invalid" : "")}");
                        foreach (var htmlString in PrependHtml)
                        {
                            prependEl.InnerHtml.AppendHtml(htmlString);
                        }
                        inputGroupEl.InnerHtml.AppendHtml(prependEl);
                    }
                    //Hidden Control to be posted when no option is selected
                    var dummyHiddenInput = new TagBuilder("input");
                    dummyHiddenInput.Attributes.Add("type", "hidden");
                    dummyHiddenInput.Attributes.Add("id", $"dummy-{FieldId}");
                    if (Value == null || ((List <string>)Value).Count == 0)
                    {
                        dummyHiddenInput.Attributes.Add("name", $"{Name}");
                    }
                    dummyHiddenInput.Attributes.Add("value", "");
                    inputGroupEl.InnerHtml.AppendHtml(dummyHiddenInput);

                    //Control
                    var selectEl = new TagBuilder("select");
                    selectEl.Attributes.Add("id", $"input-{FieldId}");
                    //Name will be attached and removed depending on if there is selected values or not, in order for the dummy to post
                    if (Value != null && ((List <string>)Value).Count > 0)
                    {
                        selectEl.Attributes.Add("name", $"{Name}");
                    }
                    selectEl.Attributes.Add("data-field-name", $"{Name}");
                    var inputElCssClassList = new List <string>();
                    inputElCssClassList.Add("form-control erp-multiselect invisible");
                    if (ValidationErrors.Count > 0)
                    {
                        inputElCssClassList.Add("is-invalid");
                    }
                    selectEl.Attributes.Add("class", String.Join(' ', inputElCssClassList));

                    var emptyOptionAdded = false;
                    if (Required)
                    {
                        selectEl.Attributes.Add("required", null);
                    }
                    else
                    {
                        var optionEl = new TagBuilder("option");
                        // Should work only with <option></option> and the select2 placeholder to be presented
                        selectEl.InnerHtml.AppendHtml(optionEl);
                        emptyOptionAdded = true;
                    }

                    selectEl.Attributes.Add("multiple", "multiple");

                    foreach (var option in Options)
                    {
                        var optionEl = new TagBuilder("option");
                        optionEl.Attributes.Add("value", option.Value);
                        if (Value != null && ((List <string>)Value).Any(x => x == option.Value))
                        {
                            optionEl.Attributes.Add("selected", null);
                        }
                        optionEl.Attributes.Add("data-icon", option.IconClass);
                        optionEl.Attributes.Add("data-color", option.Color);
                        optionEl.InnerHtml.Append(option.Label);
                        selectEl.InnerHtml.AppendHtml(optionEl);
                    }

                    //At least one option should be in the select so it can submit
                    if (!emptyOptionAdded && Options.Count == 0)
                    {
                        var optionEl = new TagBuilder("option");
                        // Should work only with <option></option> and the select2 placeholder to be presented
                        selectEl.InnerHtml.AppendHtml(optionEl);
                    }

                    inputGroupEl.InnerHtml.AppendHtml(selectEl);
                    //Append
                    if (AppendHtml.Count > 0)
                    {
                        var appendEl = new TagBuilder("span");
                        appendEl.AddCssClass($"input-group-append {(ValidationErrors.Count > 0 ? "is-invalid" : "")}");

                        foreach (var htmlString in AppendHtml)
                        {
                            appendEl.InnerHtml.AppendHtml(htmlString);
                        }
                        inputGroupEl.InnerHtml.AppendHtml(appendEl);
                    }

                    output.Content.AppendHtml(inputGroupEl);

                    var jsCompressor = new JavaScriptCompressor();

                    #region << Init Select2 >>
                    {
                        var wvLibraryInitialized = false;
                        var libraryItemsKey      = "WebVella-" + "select2";
                        if (ViewContext.HttpContext.Items.ContainsKey(libraryItemsKey))
                        {
                            var tagHelperContext = (WvTagHelperContext)ViewContext.HttpContext.Items[libraryItemsKey];
                            wvLibraryInitialized = tagHelperContext.Initialized;
                        }

                        if (!wvLibraryInitialized)
                        {
                            {
                                var libCssEl = new TagBuilder("link");
                                libCssEl.Attributes.Add("href", "/_content/WebVella.TagHelpers/lib/select2/css/select2.min.css");
                                libCssEl.Attributes.Add("type", "text/css");
                                libCssEl.Attributes.Add("rel", "stylesheet");
                                output.PostContent.AppendHtml(libCssEl);
                                output.PostContent.AppendHtml("\r\n\t");
                            }
                            {
                                var libCssEl = new TagBuilder("link");
                                libCssEl.Attributes.Add("href", "/_content/WebVella.TagHelpers/lib/select2-bootstrap-theme/select2-bootstrap4.css");
                                libCssEl.Attributes.Add("type", "text/css");
                                libCssEl.Attributes.Add("rel", "stylesheet");
                                output.PostContent.AppendHtml(libCssEl);
                                output.PostContent.AppendHtml("\r\n\t");
                            }

                            var libJsEl = new TagBuilder("script");
                            libJsEl.Attributes.Add("type", "text/javascript");
                            libJsEl.Attributes.Add("src", "/_content/WebVella.TagHelpers/lib/select2/js/select2.min.js");
                            output.PostContent.AppendHtml(libJsEl);
                            output.PostContent.AppendHtml("\r\n\t");

                            ViewContext.HttpContext.Items[libraryItemsKey] = new WvTagHelperContext()
                            {
                                Initialized = true
                            };
                        }
                    }
                    #endregion

                    #region << Init Scripts >>
                    var tagHelperInitialized = false;
                    if (ViewContext.HttpContext.Items.ContainsKey(typeof(WvFieldMultiSelect) + "-form"))
                    {
                        var tagHelperContext = (WvTagHelperContext)ViewContext.HttpContext.Items[typeof(WvFieldMultiSelect) + "-form"];
                        tagHelperInitialized = tagHelperContext.Initialized;
                    }
                    if (!tagHelperInitialized)
                    {
                        var scriptContent = WvHelpers.GetEmbeddedTextResource("form.js", "WebVella.TagHelpers.TagHelpers.WvFieldMultiSelect", "WebVella.TagHelpers");
                        var scriptEl      = new TagBuilder("script");
                        scriptEl.Attributes.Add("type", "text/javascript");
                        scriptEl.InnerHtml.AppendHtml(jsCompressor.Compress(scriptContent));
                        //scriptEl.InnerHtml.AppendHtml(scriptContent);
                        output.PostContent.AppendHtml(scriptEl);

                        ViewContext.HttpContext.Items[typeof(WvFieldMultiSelect) + "-form"] = new WvTagHelperContext()
                        {
                            Initialized = true
                        };
                    }
                    #endregion

                    #region << Add Inline Init Script for this instance >>
                    var initScript = new TagBuilder("script");
                    initScript.Attributes.Add("type", "text/javascript");
                    var scriptTemplate = @"
						$(function(){
							MultiSelectFormInit(""{{FieldId}}"",""{{Name}}"",{{ConfigJson}});
						});"                        ;
                    scriptTemplate = scriptTemplate.Replace("{{FieldId}}", (FieldId != null ? FieldId.Value.ToString() : ""));
                    scriptTemplate = scriptTemplate.Replace("{{Name}}", Name);

                    var fieldConfig = new WvFieldMultiSelectConfig()
                    {
                        ApiUrl            = ApiUrl,
                        CanAddValues      = Access == WvFieldAccess.FullAndCreate ? true : false,
                        AjaxDatasource    = AjaxDatasource,
                        AjaxDatasourceApi = AjaxDatasourceApi,
                        SelectMatchType   = SelectMatchType,
                        Placeholder       = Placeholder
                    };

                    scriptTemplate = scriptTemplate.Replace("{{ConfigJson}}", JsonConvert.SerializeObject(fieldConfig));

                    initScript.InnerHtml.AppendHtml(jsCompressor.Compress(scriptTemplate));

                    output.PostContent.AppendHtml(initScript);
                    #endregion


                    //TODO Implement CanAddValues
                    //@if (config.CanAddValues ?? false)
                    //{
                    //	<div id="*****@*****.**" class="modal" data-backdrop="true">
                    //		<div class="modal-dialog" name="add-option">
                    //			<div class="modal-content">
                    //				<div class="modal-header">
                    //					<h5 class="modal-title">Add @(fieldMeta.Label)</h5>
                    //				</div>
                    //				<div class="modal-body">
                    //					<div class="alert alert-danger d-none"></div>
                    //					<div class="form-group">
                    //						<label class="control-label">New value</label>
                    //						<input class="form-control erp-multiselect add-option-input" value="" required/>
                    //					</div>
                    //				</div>
                    //				<div class="modal-footer">
                    //					<button class="btn btn-primary btn-sm" type="submit"><i class="fa fa-plus-circle"></i> Add</button>
                    //					<button class="btn btn-secondary btn-sm" data-dismiss="modal">Close</button>
                    //				</div>
                    //			</div>
                    //		</div>
                    //	</div>

                    //}
                }
                else if (Access == WvFieldAccess.ReadOnly)
                {
                    //Have to render it as a normal select as readonly prop does not work with select 2. Also in order for the select not to work it should be disabled,
                    //which will not pass the value, this the hidden input

                    var hiddenInput = new TagBuilder("input");
                    hiddenInput.Attributes.Add("type", "hidden");
                    hiddenInput.Attributes.Add("id", $"input-{FieldId}");
                    hiddenInput.Attributes.Add("name", $"{Name}");
                    hiddenInput.Attributes.Add("value", (Value ?? "").ToString());
                    output.Content.AppendHtml(hiddenInput);


                    var inputGroupEl = new TagBuilder("div");
                    inputGroupEl.AddCssClass("input-group");
                    //Prepend
                    if (PrependHtml.Count > 0)
                    {
                        var prependEl = new TagBuilder("span");
                        prependEl.AddCssClass($"input-group-prepend {(ValidationErrors.Count > 0 ? "is-invalid" : "")}");
                        foreach (var htmlString in PrependHtml)
                        {
                            prependEl.InnerHtml.AppendHtml(htmlString);
                        }
                        inputGroupEl.InnerHtml.AppendHtml(prependEl);
                    }


                    //Control
                    var selectEl = new TagBuilder("select");
                    selectEl.Attributes.Add("id", $"select-{FieldId}");
                    selectEl.Attributes.Add("readonly", null);
                    selectEl.Attributes.Add("disabled", $"disabled");
                    var inputElCssClassList = new List <string>();
                    inputElCssClassList.Add("form-control erp-multiselect invisible");
                    if (ValidationErrors.Count > 0)
                    {
                        inputElCssClassList.Add("is-invalid");
                    }
                    selectEl.Attributes.Add("class", String.Join(' ', inputElCssClassList));
                    if (Required)
                    {
                        selectEl.Attributes.Add("required", null);
                    }

                    selectEl.Attributes.Add("multiple", "multiple");

                    foreach (var option in Options)
                    {
                        var optionEl = new TagBuilder("option");
                        optionEl.Attributes.Add("value", option.Value);
                        if (Value != null && ((List <string>)Value).Any(x => x == option.Value))
                        {
                            optionEl.Attributes.Add("selected", null);
                        }
                        optionEl.Attributes.Add("data-icon", option.IconClass);
                        optionEl.Attributes.Add("data-color", option.Color);
                        optionEl.InnerHtml.Append(option.Label);
                        selectEl.InnerHtml.AppendHtml(optionEl);
                    }

                    inputGroupEl.InnerHtml.AppendHtml(selectEl);
                    //Append
                    if (AppendHtml.Count > 0)
                    {
                        var appendEl = new TagBuilder("span");
                        appendEl.AddCssClass($"input-group-append {(ValidationErrors.Count > 0 ? "is-invalid" : "")}");

                        foreach (var htmlString in AppendHtml)
                        {
                            appendEl.InnerHtml.AppendHtml(htmlString);
                        }
                        inputGroupEl.InnerHtml.AppendHtml(appendEl);
                    }

                    output.Content.AppendHtml(inputGroupEl);
                }
            }
            else if (Mode == WvFieldRenderMode.Display)
            {
                if (((List <string>)Value).Count > 0)
                {
                    var select2ContainerEl = new TagBuilder("span");
                    select2ContainerEl.Attributes.Add("id", $"input-{FieldId}");
                    select2ContainerEl.AddCssClass("select2 select2-container select2-container--bootstrap4 d-block disabled clean");

                    var select2SelectionEl = new TagBuilder("span");
                    select2SelectionEl.AddCssClass("selection");

                    var select2SelectionInnerEl = new TagBuilder("span");
                    select2SelectionInnerEl.AddCssClass("select2-selection select2-selection--multiple d-flex");

                    var select2SelectionUlEl = new TagBuilder("ul");
                    select2SelectionUlEl.AddCssClass("select2-selection__rendered");

                    foreach (var dataKey in Value)
                    {
                        var optionEl = new TagBuilder("li");
                        var option   = Options.FirstOrDefault(x => x.Value == dataKey);
                        if (option == null)
                        {
                            optionEl.AddCssClass("select2-selection__choice missing");
                            optionEl.Attributes.Add("title", dataKey);
                            optionEl.Attributes.Add("data-key", dataKey);
                            optionEl.InnerHtml.Append(dataKey);
                            if (Value != null && (Value.ToString() != ""))
                            {
                                var optionElIcon = new TagBuilder("span");
                                optionElIcon.AddCssClass("fa fa-fw fa-exclamation-circle go-red");
                                optionElIcon.Attributes.Add("title", "the value is not supported by this field anymore");
                                optionEl.InnerHtml.AppendHtml(optionElIcon);
                            }
                        }
                        else
                        {
                            optionEl.AddCssClass("select2-selection__choice");
                            optionEl.Attributes.Add("title", option.Label);
                            optionEl.Attributes.Add("data-key", dataKey);
                            if (String.IsNullOrWhiteSpace(option.IconClass))
                            {
                                optionEl.InnerHtml.Append(option.Label);
                            }
                            else
                            {
                                var color = "#999";
                                if (!String.IsNullOrWhiteSpace(option.Color))
                                {
                                    color = option.Color;
                                }

                                optionEl.InnerHtml.AppendHtml($"<i class=\"{option.IconClass}\" style=\"color:{color}\"></i> {option.Label}");
                            }
                        }
                        select2SelectionUlEl.InnerHtml.AppendHtml(optionEl);
                    }

                    select2SelectionInnerEl.InnerHtml.AppendHtml(select2SelectionUlEl);
                    select2SelectionEl.InnerHtml.AppendHtml(select2SelectionInnerEl);
                    select2ContainerEl.InnerHtml.AppendHtml(select2SelectionEl);

                    output.Content.AppendHtml(select2ContainerEl);
                }
                else
                {
                    output.Content.AppendHtml(EmptyValEl);
                }
            }
            else if (Mode == WvFieldRenderMode.Simple)
            {
                output.SuppressOutput();
                var valueLabels = new List <string>();
                foreach (var dataKey in (List <string>)Value)
                {
                    var option = Options.FirstOrDefault(x => x.Value == dataKey);
                    if (option == null)
                    {
                        valueLabels.Add(dataKey);
                    }
                    else
                    {
                        if (String.IsNullOrWhiteSpace(option.IconClass))
                        {
                            valueLabels.Add(option.Label);
                        }
                        else
                        {
                            var color = "#999";
                            if (!String.IsNullOrWhiteSpace(option.Color))
                            {
                                color = option.Color;
                            }

                            valueLabels.Add($"<i class=\"{option.IconClass}\" style=\"color:{color}\"></i> {option.Label}");
                        }
                    }
                }

                output.Content.AppendHtml(String.Join(", ", valueLabels));
                return;
            }
            else if (Mode == WvFieldRenderMode.InlineEdit)
            {
                if (Access == WvFieldAccess.Full || Access == WvFieldAccess.FullAndCreate)
                {
                    #region << View Wrapper >>
                    {
                        var viewWrapperEl = new TagBuilder("div");
                        viewWrapperEl.AddCssClass("input-group view-wrapper");
                        viewWrapperEl.Attributes.Add("title", "double click to edit");
                        viewWrapperEl.Attributes.Add("id", $"view-{FieldId}");

                        //Prepend
                        if (PrependHtml.Count > 0)
                        {
                            var viewInputPrepend = new TagBuilder("span");
                            viewInputPrepend.AddCssClass("input-group-prepend");
                            foreach (var htmlString in PrependHtml)
                            {
                                viewInputPrepend.InnerHtml.AppendHtml(htmlString);
                            }
                            viewWrapperEl.InnerHtml.AppendHtml(viewInputPrepend);
                        }
                        //Control
                        var viewFormControlEl = new TagBuilder("div");
                        viewFormControlEl.AddCssClass("form-control erp-multiselect");

                        var select2ContainerEl = new TagBuilder("span");
                        select2ContainerEl.AddCssClass("select2 select2-container select2-container--bootstrap4 d-block disabled");

                        var select2SelectionEl = new TagBuilder("span");
                        select2SelectionEl.AddCssClass("selection");

                        var select2SelectionInnerEl = new TagBuilder("span");
                        select2SelectionInnerEl.AddCssClass("select2-selection select2-selection--multiple");

                        var select2SelectionUlEl = new TagBuilder("ul");
                        select2SelectionUlEl.AddCssClass("select2-selection__rendered");

                        foreach (var dataKey in Value)
                        {
                            var optionEl = new TagBuilder("li");
                            var option   = Options.FirstOrDefault(x => x.Value == dataKey);
                            if (option == null)
                            {
                                optionEl.AddCssClass("select2-selection__choice missing");
                                optionEl.Attributes.Add("title", dataKey);
                                optionEl.Attributes.Add("data-key", dataKey);
                                optionEl.InnerHtml.Append(dataKey);
                                if (Value != null && (Value.ToString() != ""))
                                {
                                    var optionElIcon = new TagBuilder("span");
                                    optionElIcon.AddCssClass("fa fa-fw fa-exclamation-circle go-red");
                                    optionElIcon.Attributes.Add("title", "the value is not supported by this field anymore");
                                    optionEl.InnerHtml.AppendHtml(optionElIcon);
                                }
                            }
                            else
                            {
                                optionEl.AddCssClass("select2-selection__choice");
                                optionEl.Attributes.Add("title", option.Label);
                                optionEl.Attributes.Add("data-key", dataKey);
                                if (String.IsNullOrWhiteSpace(option.IconClass))
                                {
                                    optionEl.InnerHtml.Append(option.Label);
                                }
                                else
                                {
                                    var color = "#999";
                                    if (!String.IsNullOrWhiteSpace(option.Color))
                                    {
                                        color = option.Color;
                                    }

                                    optionEl.InnerHtml.AppendHtml($"<i class=\"{option.IconClass}\" style=\"color:{color}\"></i> {option.Label}");
                                }
                            }
                            select2SelectionUlEl.InnerHtml.AppendHtml(optionEl);
                        }

                        select2SelectionInnerEl.InnerHtml.AppendHtml(select2SelectionUlEl);
                        select2SelectionEl.InnerHtml.AppendHtml(select2SelectionInnerEl);
                        select2ContainerEl.InnerHtml.AppendHtml(select2SelectionEl);
                        viewFormControlEl.InnerHtml.AppendHtml(select2ContainerEl);
                        viewWrapperEl.InnerHtml.AppendHtml(viewFormControlEl);

                        //Append
                        var viewInputActionEl = new TagBuilder("span");
                        viewInputActionEl.AddCssClass("input-group-append action");
                        foreach (var htmlString in AppendHtml)
                        {
                            viewInputActionEl.InnerHtml.AppendHtml(htmlString);
                        }
                        viewInputActionEl.InnerHtml.AppendHtml("<button type=\"button\" class='btn btn-white' title='edit'><i class='fa fa-fw fa-pencil-alt'></i></button>");
                        viewWrapperEl.InnerHtml.AppendHtml(viewInputActionEl);
                        output.Content.AppendHtml(viewWrapperEl);
                    }
                    #endregion

                    #region << Edit Wrapper>>
                    {
                        var editWrapperEl = new TagBuilder("div");
                        editWrapperEl.Attributes.Add("id", $"edit-{FieldId}");
                        editWrapperEl.Attributes.Add("style", $"display:none;");
                        editWrapperEl.AddCssClass("edit-wrapper");

                        var editInputGroupEl = new TagBuilder("div");
                        editInputGroupEl.AddCssClass("input-group");
                        //Prepend
                        if (PrependHtml.Count > 0)
                        {
                            var editInputPrepend = new TagBuilder("span");
                            editInputPrepend.AddCssClass("input-group-prepend");
                            foreach (var htmlString in PrependHtml)
                            {
                                editInputPrepend.InnerHtml.AppendHtml(htmlString);
                            }
                            editInputGroupEl.InnerHtml.AppendHtml(editInputPrepend);
                        }
                        //Control
                        var formControl         = new TagBuilder("div");
                        var inputElCssClassList = new List <string>();
                        inputElCssClassList.Add("form-control erp-multiselect");
                        if (ValidationErrors.Count > 0)
                        {
                            inputElCssClassList.Add("is-invalid");
                        }
                        formControl.Attributes.Add("class", String.Join(' ', inputElCssClassList));

                        var selectEl = new TagBuilder("select");
                        selectEl.Attributes.Add("id", $"input-{FieldId}");
                        selectEl.Attributes.Add("name", $"{Name}");
                        var emptyOptionAdded = false;
                        if (Required)
                        {
                            selectEl.Attributes.Add("required", null);
                        }
                        else
                        {
                            var optionEl = new TagBuilder("option");
                            // Should work only with <option></option> and the select2 placeholder to be presented
                            selectEl.InnerHtml.AppendHtml(optionEl);
                            emptyOptionAdded = true;
                        }
                        selectEl.Attributes.Add("multiple", "multiple");
                        selectEl.Attributes.Add("data-original-value", JsonConvert.SerializeObject((Value ?? "").ToString()));


                        foreach (var option in Options)
                        {
                            var optionEl = new TagBuilder("option");
                            optionEl.Attributes.Add("value", option.Value);
                            if (((List <string>)Value).Any(x => x == option.Value))
                            {
                                optionEl.Attributes.Add("selected", null);
                            }
                            optionEl.Attributes.Add("data-icon", option.IconClass);
                            optionEl.Attributes.Add("data-color", option.Color);
                            optionEl.InnerHtml.Append(option.Label);
                            selectEl.InnerHtml.AppendHtml(optionEl);
                        }

                        //At least one option should be in the select so it can submit
                        if (!emptyOptionAdded && Options.Count == 0)
                        {
                            var optionEl = new TagBuilder("option");
                            // Should work only with <option></option> and the select2 placeholder to be presented
                            selectEl.InnerHtml.AppendHtml(optionEl);
                        }
                        formControl.InnerHtml.AppendHtml(selectEl);
                        editInputGroupEl.InnerHtml.AppendHtml(formControl);

                        //Append
                        var editInputGroupAppendEl = new TagBuilder("span");
                        editInputGroupAppendEl.AddCssClass("input-group-append");

                        foreach (var htmlString in AppendHtml)
                        {
                            editInputGroupAppendEl.InnerHtml.AppendHtml(htmlString);
                        }
                        editInputGroupAppendEl.InnerHtml.AppendHtml("<button type=\"button\" class='btn btn-white save' title='save'><i class='fa fa-fw fa-check go-green'></i></button>");
                        editInputGroupAppendEl.InnerHtml.AppendHtml("<button type=\"button\" class='btn btn-white cancel' title='cancel'><i class='fa fa-fw fa-times go-gray'></i></button>");
                        editInputGroupEl.InnerHtml.AppendHtml(editInputGroupAppendEl);

                        editWrapperEl.InnerHtml.AppendHtml(editInputGroupEl);

                        output.Content.AppendHtml(editWrapperEl);
                    }
                    #endregion

                    var jsCompressor = new JavaScriptCompressor();

                    #region << Init Select2 >>
                    {
                        var wvLibraryInitialized = false;
                        var libraryItemsKey      = "WebVella-" + "select2";
                        if (ViewContext.HttpContext.Items.ContainsKey(libraryItemsKey))
                        {
                            var tagHelperContext = (WvTagHelperContext)ViewContext.HttpContext.Items[libraryItemsKey];
                            wvLibraryInitialized = tagHelperContext.Initialized;
                        }

                        if (!wvLibraryInitialized)
                        {
                            {
                                var libCssEl = new TagBuilder("link");
                                libCssEl.Attributes.Add("href", "/_content/WebVella.TagHelpers/lib/select2/css/select2.min.css");
                                libCssEl.Attributes.Add("type", "text/css");
                                libCssEl.Attributes.Add("rel", "stylesheet");
                                output.PostContent.AppendHtml(libCssEl);
                                output.PostContent.AppendHtml("\r\n\t");
                            }
                            {
                                var libCssEl = new TagBuilder("link");
                                libCssEl.Attributes.Add("href", "/_content/WebVella.TagHelpers/lib/select2-bootstrap-theme/select2-bootstrap4.css");
                                libCssEl.Attributes.Add("type", "text/css");
                                libCssEl.Attributes.Add("rel", "stylesheet");
                                output.PostContent.AppendHtml(libCssEl);
                                output.PostContent.AppendHtml("\r\n\t");
                            }

                            var libJsEl = new TagBuilder("script");
                            libJsEl.Attributes.Add("type", "text/javascript");
                            libJsEl.Attributes.Add("src", "/_content/WebVella.TagHelpers/lib/select2/js/select2.min.js");
                            output.PostContent.AppendHtml(libJsEl);
                            output.PostContent.AppendHtml("\r\n\t");

                            ViewContext.HttpContext.Items[libraryItemsKey] = new WvTagHelperContext()
                            {
                                Initialized = true
                            };
                        }
                    }
                    #endregion

                    #region << Init Scripts >>
                    var tagHelperInitialized = false;
                    if (ViewContext.HttpContext.Items.ContainsKey(typeof(WvFieldMultiSelect) + "-inline-edit"))
                    {
                        var tagHelperContext = (WvTagHelperContext)ViewContext.HttpContext.Items[typeof(WvFieldMultiSelect) + "-inline-edit"];
                        tagHelperInitialized = tagHelperContext.Initialized;
                    }
                    if (!tagHelperInitialized)
                    {
                        var scriptContent = WvHelpers.GetEmbeddedTextResource("inline-edit.js", "WebVella.TagHelpers.TagHelpers.WvFieldMultiSelect", "WebVella.TagHelpers");
                        var scriptEl      = new TagBuilder("script");
                        scriptEl.Attributes.Add("type", "text/javascript");
                        //scriptEl.InnerHtml.AppendHtml(jsCompressor.Compress(scriptContent));
                        scriptEl.InnerHtml.AppendHtml(scriptContent);
                        output.PostContent.AppendHtml(scriptEl);

                        ViewContext.HttpContext.Items[typeof(WvFieldMultiSelect) + "-inline-edit"] = new WvTagHelperContext()
                        {
                            Initialized = true
                        };
                    }
                    #endregion

                    #region << Add Inline Init Script for this instance >>
                    var initScript = new TagBuilder("script");
                    initScript.Attributes.Add("type", "text/javascript");
                    var scriptTemplate = @"
						$(function(){
							MultiSelectInlineEditInit(""{{FieldId}}"",""{{Name}}"",{{ConfigJson}});
						});"                        ;
                    scriptTemplate = scriptTemplate.Replace("{{FieldId}}", (FieldId != null ? FieldId.Value.ToString() : ""));
                    scriptTemplate = scriptTemplate.Replace("{{Name}}", Name);

                    var fieldConfig = new WvFieldMultiSelectConfig()
                    {
                        ApiUrl            = ApiUrl,
                        CanAddValues      = Access == WvFieldAccess.FullAndCreate ? true : false,
                        AjaxDatasource    = AjaxDatasource,
                        AjaxDatasourceApi = AjaxDatasourceApi,
                        SelectMatchType   = SelectMatchType,
                        Placeholder       = Placeholder
                    };

                    scriptTemplate = scriptTemplate.Replace("{{ConfigJson}}", JsonConvert.SerializeObject(fieldConfig));

                    initScript.InnerHtml.AppendHtml(jsCompressor.Compress(scriptTemplate));

                    output.PostContent.AppendHtml(initScript);
                    #endregion
                }
                else if (Access == WvFieldAccess.ReadOnly)
                {
                    var divEl = new TagBuilder("div");
                    divEl.AddCssClass("input-group");
                    //Prepend
                    if (PrependHtml.Count > 0)
                    {
                        var viewInputPrepend = new TagBuilder("span");
                        viewInputPrepend.AddCssClass("input-group-prepend");
                        foreach (var htmlString in PrependHtml)
                        {
                            viewInputPrepend.InnerHtml.AppendHtml(htmlString);
                        }
                        divEl.InnerHtml.AppendHtml(viewInputPrepend);
                    }
                    //Control
                    var viewFormControlEl = new TagBuilder("div");
                    viewFormControlEl.AddCssClass("form-control erp-multiselect");

                    var select2ContainerEl = new TagBuilder("span");
                    select2ContainerEl.AddCssClass("select2 select2-container select2-container--bootstrap4 d-block disabled");

                    var select2SelectionEl = new TagBuilder("span");
                    select2SelectionEl.AddCssClass("selection");

                    var select2SelectionInnerEl = new TagBuilder("span");
                    select2SelectionInnerEl.AddCssClass("select2-selection select2-selection--multiple");

                    var select2SelectionUlEl = new TagBuilder("ul");
                    select2SelectionUlEl.AddCssClass("select2-selection__rendered");

                    foreach (var dataKey in Value)
                    {
                        var optionEl = new TagBuilder("li");
                        var option   = Options.FirstOrDefault(x => x.Value == dataKey);
                        if (option == null)
                        {
                            optionEl.AddCssClass("select2-selection__choice missing");
                            optionEl.Attributes.Add("title", dataKey);
                            optionEl.Attributes.Add("data-key", dataKey);
                            optionEl.InnerHtml.Append(dataKey);
                            if (Value != null && (Value.ToString() != ""))
                            {
                                var optionElIcon = new TagBuilder("span");
                                optionElIcon.AddCssClass("fa fa-fw fa-exclamation-circle go-red");
                                optionElIcon.Attributes.Add("title", "the value is not supported by this field anymore");
                                optionEl.InnerHtml.AppendHtml(optionElIcon);
                            }
                        }
                        else
                        {
                            optionEl.AddCssClass("select2-selection__choice");
                            optionEl.Attributes.Add("title", option.Label);
                            optionEl.Attributes.Add("data-key", dataKey);
                            if (String.IsNullOrWhiteSpace(option.IconClass))
                            {
                                optionEl.InnerHtml.Append(option.Label);
                            }
                            else
                            {
                                var color = "#999";
                                if (!String.IsNullOrWhiteSpace(option.Color))
                                {
                                    color = option.Color;
                                }

                                optionEl.InnerHtml.AppendHtml($"<i class=\"{option.IconClass}\" style=\"color:{color}\"></i> {option.Label}");
                            }
                        }
                        select2SelectionUlEl.InnerHtml.AppendHtml(optionEl);
                    }
                    select2SelectionInnerEl.InnerHtml.AppendHtml(select2SelectionUlEl);
                    select2SelectionEl.InnerHtml.AppendHtml(select2SelectionInnerEl);
                    select2ContainerEl.InnerHtml.AppendHtml(select2SelectionEl);
                    viewFormControlEl.InnerHtml.AppendHtml(select2ContainerEl);
                    divEl.InnerHtml.AppendHtml(viewFormControlEl);

                    //Append
                    var appendActionSpan = new TagBuilder("span");
                    appendActionSpan.AddCssClass("input-group-append action");
                    foreach (var htmlString in AppendHtml)
                    {
                        appendActionSpan.InnerHtml.AppendHtml(htmlString);
                    }
                    appendActionSpan.InnerHtml.AppendHtml("<button type=\"button\" disabled class='btn btn-white' title='locked'><i class='fa fa-fw fa-lock'></i></button>");
                    divEl.InnerHtml.AppendHtml(appendActionSpan);

                    output.Content.AppendHtml(divEl);
                }
            }
            #endregion


            //Finally
            if (SubInputEl != null)
            {
                output.PostContent.AppendHtml(SubInputEl);
            }

            return;
        }
Example #2
0
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            if (!isVisible)
            {
                output.SuppressOutput();
                return;
            }
            #region << Init >>
            var initSuccess = InitField(context, output);

            if (!initSuccess)
            {
                return;
            }

            #region << Init Prepend and Append >>
            var content = await output.GetChildContentAsync();

            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(content.GetContent());
            var prependTaghelper = htmlDoc.DocumentNode.Descendants("wv-field-prepend");
            var appendTagHelper  = htmlDoc.DocumentNode.Descendants("wv-field-append");

            foreach (var node in prependTaghelper)
            {
                PrependHtml.Add(node.InnerHtml.ToString());
            }

            foreach (var node in appendTagHelper)
            {
                AppendHtml.Add(node.InnerHtml.ToString());
            }

            #endregion


            #region << Validate Options >>
            if (Options == null)
            {
                var divEl = new TagBuilder("div");
                divEl.AddCssClass("form-control-plaintext erp-plain-text");

                var errorListEl = new TagBuilder("ul");
                errorListEl.AddCssClass("erp-error-list list-unstyled");

                var errorEl = new TagBuilder("li");
                errorEl.AddCssClass("go-red");

                var iconEl = new TagBuilder("span");
                iconEl.AddCssClass("fa fa-fw fa-exclamation");

                errorEl.InnerHtml.AppendHtml(iconEl);
                errorEl.InnerHtml.Append($"Error:Select options cannot be null");

                errorListEl.InnerHtml.AppendHtml(errorEl);
                divEl.InnerHtml.AppendHtml(errorListEl);
                output.Content.AppendHtml(divEl);
                //Finally
                if (SubInputEl != null)
                {
                    output.PostContent.AppendHtml(SubInputEl);
                }
                return;
            }
            #endregion

            #endregion

            #region << Render >>
            if (Mode == FieldRenderMode.Form)
            {
                if (Access == FieldAccess.Full || Access == FieldAccess.FullAndCreate)
                {
                    var inputGroupEl = new TagBuilder("div");
                    inputGroupEl.AddCssClass("input-group");
                    //Prepend
                    if (PrependHtml.Count > 0)
                    {
                        var prependEl = new TagBuilder("span");
                        prependEl.AddCssClass($"input-group-prepend {(ValidationErrors.Count > 0 ? "is-invalid" : "")}");
                        foreach (var htmlString in PrependHtml)
                        {
                            prependEl.InnerHtml.AppendHtml(htmlString);
                        }
                        inputGroupEl.InnerHtml.AppendHtml(prependEl);
                    }
                    //Control
                    var selectEl = new TagBuilder("select");
                    selectEl.Attributes.Add("id", $"input-{FieldId}");
                    selectEl.Attributes.Add("name", $"{Name}");
                    var inputElCssClassList = new List <string>();
                    inputElCssClassList.Add("form-control erp-multiselect invisible");
                    if (ValidationErrors.Count > 0)
                    {
                        inputElCssClassList.Add("is-invalid");
                    }
                    selectEl.Attributes.Add("class", String.Join(' ', inputElCssClassList));
                    if (Required)
                    {
                        selectEl.Attributes.Add("required", null);
                    }
                    selectEl.Attributes.Add("multiple", "multiple");

                    foreach (var option in Options)
                    {
                        var optionEl = new TagBuilder("option");
                        optionEl.Attributes.Add("value", option.Value);
                        if (Value != null && ((List <string>)Value).Any(x => x == option.Value))
                        {
                            optionEl.Attributes.Add("selected", null);
                        }
                        optionEl.InnerHtml.Append(option.Label);
                        selectEl.InnerHtml.AppendHtml(optionEl);
                    }

                    inputGroupEl.InnerHtml.AppendHtml(selectEl);
                    //Append
                    if (AppendHtml.Count > 0)
                    {
                        var appendEl = new TagBuilder("span");
                        appendEl.AddCssClass($"input-group-append {(ValidationErrors.Count > 0 ? "is-invalid" : "")}");

                        foreach (var htmlString in AppendHtml)
                        {
                            appendEl.InnerHtml.AppendHtml(htmlString);
                        }
                        inputGroupEl.InnerHtml.AppendHtml(appendEl);
                    }

                    output.Content.AppendHtml(inputGroupEl);

                    var jsCompressor = new JavaScriptCompressor();

                    #region << Init Scripts >>
                    var tagHelperInitialized = false;
                    if (ViewContext.HttpContext.Items.ContainsKey(typeof(WvFieldMultiSelect) + "-form"))
                    {
                        var tagHelperContext = (WvTagHelperContext)ViewContext.HttpContext.Items[typeof(WvFieldMultiSelect) + "-form"];
                        tagHelperInitialized = tagHelperContext.Initialized;
                    }
                    if (!tagHelperInitialized)
                    {
                        var scriptContent = FileService.GetEmbeddedTextResource("form.js", "WebVella.Erp.Web.TagHelpers.WvFieldMultiSelect");
                        var scriptEl      = new TagBuilder("script");
                        scriptEl.Attributes.Add("type", "text/javascript");
                        scriptEl.InnerHtml.AppendHtml(jsCompressor.Compress(scriptContent));
                        //scriptEl.InnerHtml.AppendHtml(scriptContent);
                        output.PostContent.AppendHtml(scriptEl);

                        ViewContext.HttpContext.Items[typeof(WvFieldMultiSelect) + "-form"] = new WvTagHelperContext()
                        {
                            Initialized = true
                        };
                    }
                    #endregion

                    #region << Add Inline Init Script for this instance >>
                    var initScript = new TagBuilder("script");
                    initScript.Attributes.Add("type", "text/javascript");
                    var scriptTemplate = @"
						$(function(){
							MultiSelectFormInit(""{{FieldId}}"",""{{Name}}"",""{{EntityName}}"",{{ConfigJson}});
						});"                        ;
                    scriptTemplate = scriptTemplate.Replace("{{FieldId}}", (FieldId ?? null).ToString());
                    scriptTemplate = scriptTemplate.Replace("{{Name}}", Name);
                    scriptTemplate = scriptTemplate.Replace("{{EntityName}}", EntityName);
                    scriptTemplate = scriptTemplate.Replace("{{RecordId}}", (RecordId ?? null).ToString());

                    var fieldConfig = new WvFieldMultiSelectConfig()
                    {
                        ApiUrl       = ApiUrl,
                        CanAddValues = Access == FieldAccess.FullAndCreate ? true : false
                    };

                    scriptTemplate = scriptTemplate.Replace("{{ConfigJson}}", JsonConvert.SerializeObject(fieldConfig));

                    initScript.InnerHtml.AppendHtml(jsCompressor.Compress(scriptTemplate));

                    output.PostContent.AppendHtml(initScript);
                    #endregion


                    //TODO Implement CanAddValues
                    //@if (config.CanAddValues ?? false)
                    //{
                    //	<div id="*****@*****.**" class="modal" data-backdrop="true">
                    //		<div class="modal-dialog" name="add-option">
                    //			<div class="modal-content">
                    //				<div class="modal-header">
                    //					<h5 class="modal-title">Add @(fieldMeta.Label)</h5>
                    //				</div>
                    //				<div class="modal-body">
                    //					<div class="alert alert-danger d-none"></div>
                    //					<div class="form-group">
                    //						<label class="control-label">New value</label>
                    //						<input class="form-control erp-multiselect add-option-input" value="" required/>
                    //					</div>
                    //				</div>
                    //				<div class="modal-footer">
                    //					<button class="btn btn-primary btn-sm" type="submit"><i class="fa fa-plus-circle"></i> Add</button>
                    //					<button class="btn btn-secondary btn-sm" data-dismiss="modal">Close</button>
                    //				</div>
                    //			</div>
                    //		</div>
                    //	</div>

                    //}
                }
                else if (Access == FieldAccess.ReadOnly)
                {
                    var inputGroupEl = new TagBuilder("div");
                    inputGroupEl.AddCssClass("input-group");

                    //Prepend
                    if (PrependHtml.Count > 0)
                    {
                        var prependEl = new TagBuilder("span");
                        prependEl.AddCssClass($"input-group-prepend {(ValidationErrors.Count > 0 ? "is-invalid" : "")}");
                        foreach (var htmlString in PrependHtml)
                        {
                            prependEl.InnerHtml.AppendHtml(htmlString);
                        }
                        inputGroupEl.InnerHtml.AppendHtml(prependEl);
                    }
                    //Control
                    var formControlEl = new TagBuilder("div");
                    formControlEl.AddCssClass("form-control erp-multiselect");

                    var select2ContainerEl = new TagBuilder("span");
                    select2ContainerEl.AddCssClass("select2 select2-container select2-container--default d-block");

                    var select2SelectionEl = new TagBuilder("span");
                    select2SelectionEl.AddCssClass("selection");

                    var select2SelectionInnerEl = new TagBuilder("span");
                    select2SelectionInnerEl.AddCssClass("select2-selection select2-selection--multiple");

                    var select2SelectionUlEl = new TagBuilder("ul");
                    select2SelectionUlEl.AddCssClass("select2-selection__rendered");

                    foreach (var dataKey in Value)
                    {
                        var optionEl = new TagBuilder("li");
                        var option   = Options.FirstOrDefault(x => x.Value == dataKey);
                        if (option == null)
                        {
                            optionEl.AddCssClass("select2-selection__choice missing");
                            optionEl.Attributes.Add("title", dataKey);
                            optionEl.Attributes.Add("data-key", dataKey);
                            optionEl.InnerHtml.Append(dataKey);
                            if (Value != null && (Value.ToString() != ""))
                            {
                                var optionElIcon = new TagBuilder("span");
                                optionElIcon.AddCssClass("fa fa-fw fa-exclamation-circle go-red");
                                optionElIcon.Attributes.Add("title", "the value is not supported by this field anymore");
                                optionEl.InnerHtml.AppendHtml(optionElIcon);
                            }
                        }
                        else
                        {
                            optionEl.AddCssClass("select2-selection__choice");
                            optionEl.Attributes.Add("title", option.Label);
                            optionEl.Attributes.Add("data-key", dataKey);
                            optionEl.InnerHtml.Append(option.Label);
                        }
                        select2SelectionUlEl.InnerHtml.AppendHtml(optionEl);
                    }

                    select2SelectionInnerEl.InnerHtml.AppendHtml(select2SelectionUlEl);
                    select2SelectionEl.InnerHtml.AppendHtml(select2SelectionInnerEl);
                    select2ContainerEl.InnerHtml.AppendHtml(select2SelectionEl);
                    formControlEl.InnerHtml.AppendHtml(select2ContainerEl);
                    inputGroupEl.InnerHtml.AppendHtml(formControlEl);
                    //Append
                    if (AppendHtml.Count > 0)
                    {
                        var appendEl = new TagBuilder("span");
                        appendEl.AddCssClass($"input-group-append {(ValidationErrors.Count > 0 ? "is-invalid" : "")}");

                        foreach (var htmlString in AppendHtml)
                        {
                            appendEl.InnerHtml.AppendHtml(htmlString);
                        }
                        inputGroupEl.InnerHtml.AppendHtml(appendEl);
                    }

                    //Hidden input with the value
                    var hiddenInput = new TagBuilder("input");
                    hiddenInput.Attributes.Add("type", "hidden");
                    hiddenInput.Attributes.Add("id", $"input-{FieldId}");
                    hiddenInput.Attributes.Add("name", Name);
                    hiddenInput.Attributes.Add("value", (Value ?? "").ToString());
                    output.Content.AppendHtml(hiddenInput);

                    output.Content.AppendHtml(inputGroupEl);
                }
            }
            else if (Mode == FieldRenderMode.Display)
            {
                if (((List <string>)Value).Count > 0)
                {
                    var select2ContainerEl = new TagBuilder("span");
                    select2ContainerEl.Attributes.Add("id", $"input-{FieldId}");
                    select2ContainerEl.AddCssClass("select2 select2-container select2-container--default d-block disabled clean");

                    var select2SelectionEl = new TagBuilder("span");
                    select2SelectionEl.AddCssClass("selection");

                    var select2SelectionInnerEl = new TagBuilder("span");
                    select2SelectionInnerEl.AddCssClass("select2-selection select2-selection--multiple");

                    var select2SelectionUlEl = new TagBuilder("ul");
                    select2SelectionUlEl.AddCssClass("select2-selection__rendered");

                    foreach (var dataKey in Value)
                    {
                        var optionEl = new TagBuilder("li");
                        var option   = Options.FirstOrDefault(x => x.Value == dataKey);
                        if (option == null)
                        {
                            optionEl.AddCssClass("select2-selection__choice missing");
                            optionEl.Attributes.Add("title", dataKey);
                            optionEl.Attributes.Add("data-key", dataKey);
                            optionEl.InnerHtml.Append(dataKey);
                            if (Value != null && (Value.ToString() != ""))
                            {
                                var optionElIcon = new TagBuilder("span");
                                optionElIcon.AddCssClass("fa fa-fw fa-exclamation-circle go-red");
                                optionElIcon.Attributes.Add("title", "the value is not supported by this field anymore");
                                optionEl.InnerHtml.AppendHtml(optionElIcon);
                            }
                        }
                        else
                        {
                            optionEl.AddCssClass("select2-selection__choice");
                            optionEl.Attributes.Add("title", option.Label);
                            optionEl.Attributes.Add("data-key", dataKey);
                            optionEl.InnerHtml.Append(option.Label);
                        }
                        select2SelectionUlEl.InnerHtml.AppendHtml(optionEl);
                    }

                    select2SelectionInnerEl.InnerHtml.AppendHtml(select2SelectionUlEl);
                    select2SelectionEl.InnerHtml.AppendHtml(select2SelectionInnerEl);
                    select2ContainerEl.InnerHtml.AppendHtml(select2SelectionEl);

                    output.Content.AppendHtml(select2ContainerEl);
                }
                else
                {
                    output.Content.AppendHtml(EmptyValEl);
                }
            }
            else if (Mode == FieldRenderMode.Simple)
            {
                output.SuppressOutput();
                var valueLabels = new List <string>();
                foreach (var dataKey in (List <string>)Value)
                {
                    var option = Options.FirstOrDefault(x => x.Value == dataKey);
                    if (option == null)
                    {
                        valueLabels.Add(dataKey);
                    }
                    else
                    {
                        valueLabels.Add(option.Label);
                    }
                }

                output.Content.AppendHtml(String.Join(", ", valueLabels));
                return;
            }
            else if (Mode == FieldRenderMode.InlineEdit)
            {
                if (Access == FieldAccess.Full || Access == FieldAccess.FullAndCreate)
                {
                    #region << View Wrapper >>
                    {
                        var viewWrapperEl = new TagBuilder("div");
                        viewWrapperEl.AddCssClass("input-group view-wrapper");
                        viewWrapperEl.Attributes.Add("title", "double click to edit");
                        viewWrapperEl.Attributes.Add("id", $"view-{FieldId}");

                        //Prepend
                        if (PrependHtml.Count > 0)
                        {
                            var viewInputPrepend = new TagBuilder("span");
                            viewInputPrepend.AddCssClass("input-group-prepend");
                            foreach (var htmlString in PrependHtml)
                            {
                                viewInputPrepend.InnerHtml.AppendHtml(htmlString);
                            }
                            viewWrapperEl.InnerHtml.AppendHtml(viewInputPrepend);
                        }
                        //Control
                        var viewFormControlEl = new TagBuilder("div");
                        viewFormControlEl.AddCssClass("form-control erp-multiselect");

                        var select2ContainerEl = new TagBuilder("span");
                        select2ContainerEl.AddCssClass("select2 select2-container select2-container--default d-block disabled");

                        var select2SelectionEl = new TagBuilder("span");
                        select2SelectionEl.AddCssClass("selection");

                        var select2SelectionInnerEl = new TagBuilder("span");
                        select2SelectionInnerEl.AddCssClass("select2-selection select2-selection--multiple");

                        var select2SelectionUlEl = new TagBuilder("ul");
                        select2SelectionUlEl.AddCssClass("select2-selection__rendered");

                        foreach (var dataKey in Value)
                        {
                            var optionEl = new TagBuilder("li");
                            var option   = Options.FirstOrDefault(x => x.Value == dataKey);
                            if (option == null)
                            {
                                optionEl.AddCssClass("select2-selection__choice missing");
                                optionEl.Attributes.Add("title", dataKey);
                                optionEl.Attributes.Add("data-key", dataKey);
                                optionEl.InnerHtml.Append(dataKey);
                                if (Value != null && (Value.ToString() != ""))
                                {
                                    var optionElIcon = new TagBuilder("span");
                                    optionElIcon.AddCssClass("fa fa-fw fa-exclamation-circle go-red");
                                    optionElIcon.Attributes.Add("title", "the value is not supported by this field anymore");
                                    optionEl.InnerHtml.AppendHtml(optionElIcon);
                                }
                            }
                            else
                            {
                                optionEl.AddCssClass("select2-selection__choice");
                                optionEl.Attributes.Add("title", option.Label);
                                optionEl.Attributes.Add("data-key", dataKey);
                                optionEl.InnerHtml.Append(option.Label);
                            }
                            select2SelectionUlEl.InnerHtml.AppendHtml(optionEl);
                        }

                        select2SelectionInnerEl.InnerHtml.AppendHtml(select2SelectionUlEl);
                        select2SelectionEl.InnerHtml.AppendHtml(select2SelectionInnerEl);
                        select2ContainerEl.InnerHtml.AppendHtml(select2SelectionEl);
                        viewFormControlEl.InnerHtml.AppendHtml(select2ContainerEl);
                        viewWrapperEl.InnerHtml.AppendHtml(viewFormControlEl);

                        //Append
                        var viewInputActionEl = new TagBuilder("span");
                        viewInputActionEl.AddCssClass("input-group-append");
                        foreach (var htmlString in AppendHtml)
                        {
                            viewInputActionEl.InnerHtml.AppendHtml(htmlString);
                        }
                        viewInputActionEl.InnerHtml.AppendHtml("<button type=\"button\" class='btn btn-white action' title='edit'><i class='fa fa-fw fa-pencil-alt'></i></button>");
                        viewWrapperEl.InnerHtml.AppendHtml(viewInputActionEl);
                        output.Content.AppendHtml(viewWrapperEl);
                    }
                    #endregion

                    #region << Edit Wrapper>>
                    {
                        var editWrapperEl = new TagBuilder("div");
                        editWrapperEl.Attributes.Add("id", $"edit-{FieldId}");
                        editWrapperEl.Attributes.Add("style", $"display:none;");
                        editWrapperEl.AddCssClass("edit-wrapper");

                        var editInputGroupEl = new TagBuilder("div");
                        editInputGroupEl.AddCssClass("input-group");
                        //Prepend
                        if (PrependHtml.Count > 0)
                        {
                            var editInputPrepend = new TagBuilder("span");
                            editInputPrepend.AddCssClass("input-group-prepend");
                            foreach (var htmlString in PrependHtml)
                            {
                                editInputPrepend.InnerHtml.AppendHtml(htmlString);
                            }
                            editInputGroupEl.InnerHtml.AppendHtml(editInputPrepend);
                        }
                        //Control
                        var formControl         = new TagBuilder("div");
                        var inputElCssClassList = new List <string>();
                        inputElCssClassList.Add("form-control erp-multiselect");
                        if (ValidationErrors.Count > 0)
                        {
                            inputElCssClassList.Add("is-invalid");
                        }
                        formControl.Attributes.Add("class", String.Join(' ', inputElCssClassList));

                        var selectEl = new TagBuilder("select");
                        selectEl.Attributes.Add("id", $"input-{FieldId}");
                        selectEl.Attributes.Add("name", $"{Name}");

                        if (Required)
                        {
                            selectEl.Attributes.Add("required", null);
                        }
                        selectEl.Attributes.Add("multiple", "multiple");
                        selectEl.Attributes.Add("data-original-value", JsonConvert.SerializeObject((Value ?? "").ToString()));


                        foreach (var option in Options)
                        {
                            var optionEl = new TagBuilder("option");
                            optionEl.Attributes.Add("value", option.Value);
                            if (((List <string>)Value).Any(x => x == option.Value))
                            {
                                optionEl.Attributes.Add("selected", null);
                            }
                            optionEl.InnerHtml.Append(option.Label);
                            selectEl.InnerHtml.AppendHtml(optionEl);
                        }

                        formControl.InnerHtml.AppendHtml(selectEl);
                        editInputGroupEl.InnerHtml.AppendHtml(formControl);

                        //Append
                        var editInputGroupAppendEl = new TagBuilder("span");
                        editInputGroupAppendEl.AddCssClass("input-group-append");

                        foreach (var htmlString in AppendHtml)
                        {
                            editInputGroupAppendEl.InnerHtml.AppendHtml(htmlString);
                        }
                        editInputGroupAppendEl.InnerHtml.AppendHtml("<button type=\"button\" class='btn btn-white save' title='save'><i class='fa fa-fw fa-check go-green'></i></button>");
                        editInputGroupAppendEl.InnerHtml.AppendHtml("<button type=\"button\" class='btn btn-white cancel' title='cancel'><i class='fa fa-fw fa-times go-gray'></i></button>");
                        editInputGroupEl.InnerHtml.AppendHtml(editInputGroupAppendEl);

                        editWrapperEl.InnerHtml.AppendHtml(editInputGroupEl);

                        output.Content.AppendHtml(editWrapperEl);
                    }
                    #endregion

                    var jsCompressor = new JavaScriptCompressor();
                    #region << Init Scripts >>
                    var tagHelperInitialized = false;
                    if (ViewContext.HttpContext.Items.ContainsKey(typeof(WvFieldMultiSelect) + "-inline-edit"))
                    {
                        var tagHelperContext = (WvTagHelperContext)ViewContext.HttpContext.Items[typeof(WvFieldMultiSelect) + "-inline-edit"];
                        tagHelperInitialized = tagHelperContext.Initialized;
                    }
                    if (!tagHelperInitialized)
                    {
                        var scriptContent = FileService.GetEmbeddedTextResource("inline-edit.js", "WebVella.Erp.Web.TagHelpers.WvFieldMultiSelect");
                        var scriptEl      = new TagBuilder("script");
                        scriptEl.Attributes.Add("type", "text/javascript");
                        scriptEl.InnerHtml.AppendHtml(jsCompressor.Compress(scriptContent));
                        output.PostContent.AppendHtml(scriptEl);

                        ViewContext.HttpContext.Items[typeof(WvFieldMultiSelect) + "-inline-edit"] = new WvTagHelperContext()
                        {
                            Initialized = true
                        };
                    }
                    #endregion

                    #region << Add Inline Init Script for this instance >>
                    var initScript = new TagBuilder("script");
                    initScript.Attributes.Add("type", "text/javascript");
                    var scriptTemplate = @"
						$(function(){
							MultiSelectInlineEditInit(""{{FieldId}}"",""{{Name}}"",""{{EntityName}}"",""{{RecordId}}"",{{ConfigJson}});
						});"                        ;
                    scriptTemplate = scriptTemplate.Replace("{{FieldId}}", (FieldId ?? null).ToString());
                    scriptTemplate = scriptTemplate.Replace("{{Name}}", Name);
                    scriptTemplate = scriptTemplate.Replace("{{EntityName}}", EntityName);
                    scriptTemplate = scriptTemplate.Replace("{{RecordId}}", (RecordId ?? null).ToString());

                    var fieldConfig = new WvFieldMultiSelectConfig()
                    {
                        ApiUrl       = ApiUrl,
                        CanAddValues = Access == FieldAccess.FullAndCreate ? true : false
                    };

                    scriptTemplate = scriptTemplate.Replace("{{ConfigJson}}", JsonConvert.SerializeObject(fieldConfig));

                    initScript.InnerHtml.AppendHtml(jsCompressor.Compress(scriptTemplate));

                    output.PostContent.AppendHtml(initScript);
                    #endregion
                }
                else if (Access == FieldAccess.ReadOnly)
                {
                    var divEl = new TagBuilder("div");
                    divEl.AddCssClass("input-group");
                    //Prepend
                    if (PrependHtml.Count > 0)
                    {
                        var viewInputPrepend = new TagBuilder("span");
                        viewInputPrepend.AddCssClass("input-group-prepend");
                        foreach (var htmlString in PrependHtml)
                        {
                            viewInputPrepend.InnerHtml.AppendHtml(htmlString);
                        }
                        divEl.InnerHtml.AppendHtml(viewInputPrepend);
                    }
                    //Control
                    var viewFormControlEl = new TagBuilder("div");
                    viewFormControlEl.AddCssClass("form-control erp-multiselect");

                    var select2ContainerEl = new TagBuilder("span");
                    select2ContainerEl.AddCssClass("select2 select2-container select2-container--default d-block disabled");

                    var select2SelectionEl = new TagBuilder("span");
                    select2SelectionEl.AddCssClass("selection");

                    var select2SelectionInnerEl = new TagBuilder("span");
                    select2SelectionInnerEl.AddCssClass("select2-selection select2-selection--multiple");

                    var select2SelectionUlEl = new TagBuilder("ul");
                    select2SelectionUlEl.AddCssClass("select2-selection__rendered");

                    foreach (var dataKey in Value)
                    {
                        var optionEl = new TagBuilder("li");
                        var option   = Options.FirstOrDefault(x => x.Value == dataKey);
                        if (option == null)
                        {
                            optionEl.AddCssClass("select2-selection__choice missing");
                            optionEl.Attributes.Add("title", dataKey);
                            optionEl.Attributes.Add("data-key", dataKey);
                            optionEl.InnerHtml.Append(dataKey);
                            if (Value != null && (Value.ToString() != ""))
                            {
                                var optionElIcon = new TagBuilder("span");
                                optionElIcon.AddCssClass("fa fa-fw fa-exclamation-circle go-red");
                                optionElIcon.Attributes.Add("title", "the value is not supported by this field anymore");
                                optionEl.InnerHtml.AppendHtml(optionElIcon);
                            }
                        }
                        else
                        {
                            optionEl.AddCssClass("select2-selection__choice");
                            optionEl.Attributes.Add("title", option.Label);
                            optionEl.Attributes.Add("data-key", dataKey);
                            optionEl.InnerHtml.Append(option.Label);
                        }
                        select2SelectionUlEl.InnerHtml.AppendHtml(optionEl);
                    }
                    select2SelectionInnerEl.InnerHtml.AppendHtml(select2SelectionUlEl);
                    select2SelectionEl.InnerHtml.AppendHtml(select2SelectionInnerEl);
                    select2ContainerEl.InnerHtml.AppendHtml(select2SelectionEl);
                    viewFormControlEl.InnerHtml.AppendHtml(select2ContainerEl);
                    divEl.InnerHtml.AppendHtml(viewFormControlEl);

                    //Append
                    var appendActionSpan = new TagBuilder("span");
                    appendActionSpan.AddCssClass("input-group-append");
                    foreach (var htmlString in AppendHtml)
                    {
                        appendActionSpan.InnerHtml.AppendHtml(htmlString);
                    }
                    appendActionSpan.InnerHtml.AppendHtml("<button type=\"button\" disabled class='btn btn-white action' title='locked'><i class='fa fa-fw fa-lock'></i></button>");
                    divEl.InnerHtml.AppendHtml(appendActionSpan);

                    output.Content.AppendHtml(divEl);
                }
            }
            #endregion


            //Finally
            if (SubInputEl != null)
            {
                output.PostContent.AppendHtml(SubInputEl);
            }

            return;
        }