Q:

Wrapping a partial view in a form and getting data on submit from it

So, short story, I have used a javascript package to create a wysiwyg editor out of a div. 
To be able to use this editor in multiple places I decided to put it in a partial view. 
I am running the site in .net core 2.2.
this is the Page that surrounds the editor
    @model NewsArticleModel
@{
    ViewData["Title"] = "EditNewsArticle";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<div class="panel">
    <div class="panel-heading">
        <h3>Edit News Article</h3>
    </div>
    <div class="panel-body">
        <br />
        <form asp-action="SaveNewsArticle" method="post">
            @Html.HiddenFor(m => m.AuthorId)
            @Html.HiddenFor(m => m.Created)
            @*@Html.HiddenFor(m => m.Editor)*@
            <div class="form-group centersm">
                @Html.LabelFor(m => m.Header, "Header", new { @class = "control-label" })
                @Html.TextBoxFor(m => m.Header, new { @class = "form-control" })
            </div>
            <div class="form-group">
                @await Html.PartialAsync("~/Views/Shared/Editor.cshtml", Model.Editor)
            </div>
            <div class="form-group">
                <div class="row">
                    <div class="col-md-4">
                        <div class="row">
                            @Html.LabelFor(m => m.ValidUntil, "Valid until", new { @class = "control-label" })
                            @Html.TextBoxFor(m => m.ValidUntil, new { @class = "form-control DatePicker" })
                        </div>
                        <div class="row">
                            @Html.CheckBoxFor(m => m.Published, new { @class = "checkbox_custom", @Text = "Publish?" })
                            @Html.LabelFor(m => m.Published, "Publish?", new { @class = "control-label" })
                        </div>                        
                    </div>
                    <div class="col-md-2"></div>
                    <div class="col-md-6">
                        Read permissions
                        @if (User.IsInRole("Officer") || User.IsInRole("Leader") || User.IsInRole("Administrator"))
                        {
                            <div class="row">
                                @Html.CheckBoxFor(m => m.ReadPermissions[0], new { @class = "checkbox_custom", @Text = "Member" })
                                @Html.LabelFor(m => m.ReadPermissions[0], "Member", new { @class = "control-label" })
                            </div>
                            <div class="row">
                                @Html.CheckBoxFor(m => m.ReadPermissions[1], new { @class = "checkbox_custom", @Text = "Officer" })
                                @Html.LabelFor(m => m.ReadPermissions[1], "Officer", new { @class = "control-label" })
                            </div>
                        }
                        @if (User.IsInRole("Leader") || User.IsInRole("Registrar") || User.IsInRole("Administrator"))
                        {
                            <div class="row">
                                @Html.CheckBoxFor(m => m.ReadPermissions[4], new { @class = "checkbox_custom", @Text = "Registrar" })
                                @Html.LabelFor(m => m.ReadPermissions[4], "Registrar", new { @class = "control-label" })
                            </div>                            
                        }
                        @if (User.IsInRole("Leader") || User.IsInRole("Administrator"))
                        {
                            <div class="row">
                                @Html.CheckBoxFor(m => m.ReadPermissions[2], new { @class = "checkbox_custom", @Text = "Leader" })
                                @Html.LabelFor(m => m.ReadPermissions[2], "Leader", new { @class = "control-label" })
                            </div>                            
                        }
                        @if (User.IsInRole("Administrator"))
                        {
                            <div class="row">
                                @Html.CheckBoxFor(m => m.ReadPermissions[3], new { @class = "checkbox_custom", @Text = "Administrator" })
                                @Html.LabelFor(m => m.ReadPermissions[3], "Administrator", new { @class = "control-label" })
                            </div>                            
                        }
                    </div>
                </div>
                <div class="form-group centersm">
                    <input type="submit" class="btn btn-primary" value="Save" />
                </div>
            </div>
        </form>
        <br />
    </div>
</div>

This is the NewsArticleModel which contains an instance of the EditorModel
public class NewsArticleModel
{
    public int Id { get; set; }

    public int AuthorId { get; set; }

    private dbUser _author;

    public dbUser Author { get { return _author ?? (_author = UserData.GetUserById(AuthorId)); } }

    public string Header { get; set; }

    public EditorModel Editor { get; set; }

    public DateTime Created { get; set; }

    public DateTime ValidUntil { get; set; }

    public bool Published { get; set; }

    /// <summary>
    /// Role Id's -1, -1 because the Role Id's are 1-indexed in the database, and an array is 0-indexed. 
    /// </summary>
    public bool[] ReadPermissions { get; set; }
}

Model.Editor here looks like this.
public class EditorModel
{
    public string Text { get; set; }
}

this is the partial view Editor.cshtml
    @model EditorModel

<script>
  $(function(){
    function initToolbarBootstrapBindings() {
      var fonts = ['Serif', 'Sans', 'Arial', 'Arial Black', 'Courier',
            'Courier New', 'Comic Sans MS', 'Helvetica', 'Impact', 'Lucida Grande', 'Lucida Sans', 'Tahoma', 'Times',
            'Times New Roman', 'Verdana'],
            fontTarget = $('[title=Font]').siblings('.dropdown-menu');
      $.each(fonts, function (idx, fontName) {
          fontTarget.append($('<li><a data-edit="fontName ' + fontName +'" style="font-family:\''+ fontName +'\'">'+fontName + '</a></li>'));
      });
      $('a[title]').tooltip({container:'body'});
        $('.dropdown-menu input').click(function() {return false;})
            .change(function () {$(this).parent('.dropdown-menu').siblings('.dropdown-toggle').dropdown('toggle');})
        .keydown('esc', function () {this.value='';$(this).change();});
      $('[data-role=magic-overlay]').each(function () {
        var overlay = $(this), target = $(overlay.data('target'));
        overlay.css('opacity', 0).css('position', 'absolute').offset(target.offset()).width(target.outerWidth()).height(target.outerHeight());
      });
      if ("onwebkitspeechchange"  in document.createElement("input")) {
        var editorOffset = $('#editor').offset();
        $('#voiceBtn').css('position','absolute').offset({top: editorOffset.top, left: editorOffset.left+$('#editor').innerWidth()-35});
      } else {
        $('#voiceBtn').hide();
      }
    };
    function showErrorAlert (reason, detail) {
        var msg='';
        if (reason==='unsupported-file-type') { msg = "Unsupported format " +detail; }
        else {
            console.log("error uploading file", reason, detail);
        }
        $('<div class="alert"> <button type="button" class="close" data-dismiss="alert">&times;</button>'+
         '<strong>File upload error</strong> '+msg+' </div>').prependTo('#alerts');
    };
    initToolbarBootstrapBindings();
    $('#editor').wysiwyg({ fileUploadError: showErrorAlert} );
    window.prettyPrint && prettyPrint();
    });

    jQuery(document).ready(function () {
        $(document).on('DOMSubtreeModified', '#editor', function(){
            $('#EditorText').val($('#editor').html());
        });
    });
</script>

@Html.HiddenFor(m => m.Text, new { id = "EditorText" })

<div class="btn-toolbar" data-role="editor-toolbar" data-target="#editor">
    <div class="btn-group">
        <a class="btn dropdown-toggle" data-toggle="dropdown" title="" data-original-title="Font"><i class="fas fa-font"></i><b class="caret"></b></a>
        <ul class="dropdown-menu">
            <li><a data-edit="fontName Serif" style="font-family:'Serif'">Serif</a></li>
            <li><a data-edit="fontName Sans" style="font-family:'Sans'">Sans</a></li>
            <li><a data-edit="fontName Arial" style="font-family:'Arial'">Arial</a></li>
            <li><a data-edit="fontName Arial Black" style="font-family:'Arial Black'">Arial Black</a></li>
            <li><a data-edit="fontName Courier" style="font-family:'Courier'">Courier</a></li>
            <li><a data-edit="fontName Courier New" style="font-family:'Courier New'">Courier New</a></li>
            <li><a data-edit="fontName Comic Sans MS" style="font-family:'Comic Sans MS'">Comic Sans MS</a></li>
            <li><a data-edit="fontName Helvetica" style="font-family:'Helvetica'">Helvetica</a></li>
            <li><a data-edit="fontName Impact" style="font-family:'Impact'">Impact</a></li>
            <li><a data-edit="fontName Lucida Grande" style="font-family:'Lucida Grande'">Lucida Grande</a></li>
            <li><a data-edit="fontName Lucida Sans" style="font-family:'Lucida Sans'">Lucida Sans</a></li>
            <li><a data-edit="fontName Tahoma" style="font-family:'Tahoma'">Tahoma</a></li>
            <li><a data-edit="fontName Times" style="font-family:'Times'">Times</a></li>
            <li><a data-edit="fontName Times New Roman" style="font-family:'Times New Roman'">Times New Roman</a></li>
            <li><a data-edit="fontName Verdana" style="font-family:'Verdana'">Verdana</a></li>
        </ul>
    </div>
    <div class="btn-group">
        <a class="btn dropdown-toggle" data-toggle="dropdown" title="" data-original-title="Font Size"><i class="fas fa-text-height"></i>&nbsp;<b class="caret"></b></a>
        <ul class="dropdown-menu">
            <li><a data-edit="fontSize 5"><font size="5">Huge</font></a></li>
            <li><a data-edit="fontSize 3"><font size="3">Normal</font></a></li>
            <li><a data-edit="fontSize 1"><font size="1">Small</font></a></li>
        </ul>
    </div>
    <div class="btn-group">
        <a class="btn" data-edit="bold" title="" data-original-title="Bold (Ctrl/Cmd+B)"><i class="fas fa-bold"></i></a>
        <a class="btn" data-edit="italic" title="" data-original-title="Italic (Ctrl/Cmd+I)"><i class="fas fa-italic"></i></a>
        <a class="btn" data-edit="strikethrough" title="" data-original-title="Strikethrough"><i class="fas fa-strikethrough"></i></a>
        <a class="btn" data-edit="underline" title="" data-original-title="Underline (Ctrl/Cmd+U)"><i class="fas fa-underline"></i></a>
    </div>
    <div class="btn-group">
        <a class="btn" data-edit="insertunorderedlist" title="" data-original-title="Bullet list"><i class="fas fa-list-ul"></i></a>
        <a class="btn" data-edit="insertorderedlist" title="" data-original-title="Number list"><i class="fas fa-list-ol"></i></a>
        <a class="btn" data-edit="outdent" title="" data-original-title="Reduce indent (Shift+Tab)"><i class="fas fa-outdent"></i></a>
        <a class="btn" data-edit="indent" title="" data-original-title="Indent (Tab)"><i class="fas fa-indent"></i></a>
    </div>
    <div class="btn-group">
        <a class="btn btn-info" data-edit="justifyleft" title="" data-original-title="Align Left (Ctrl/Cmd+L)"><i class="fas fa-align-left"></i></a>
        <a class="btn" data-edit="justifycenter" title="" data-original-title="Center (Ctrl/Cmd+E)"><i class="fas fa-align-center"></i></a>
        <a class="btn" data-edit="justifyright" title="" data-original-title="Align Right (Ctrl/Cmd+R)"><i class="fas fa-align-right"></i></a>
        <a class="btn" data-edit="justifyfull" title="" data-original-title="Justify (Ctrl/Cmd+J)"><i class="fas fa-align-justify"></i></a>
    </div>
    <div class="btn-group">
        <a class="btn dropdown-toggle" data-toggle="dropdown" title="" data-original-title="Hyperlink"><i class="fas fa-link"></i></a>
        <div class="dropdown-menu input-append">
            <input class="span2" placeholder="URL" type="text" data-edit="createLink">
            <button class="btn" type="button">Add</button>
        </div>
        <a class="btn" data-edit="unlink" title="" data-original-title="Remove Hyperlink"><i class="fas fa-cut"></i></a>

    </div>

    @*<div class="btn-group">
            <a class="btn" title="" id="pictureBtn" data-original-title="Insert picture (or just drag &amp; drop)"><i class="fas fa-image"></i></a>
            <input type="file" data-role="magic-overlay" data-target="#pictureBtn" data-edit="insertImage" style="opacity: 0; position: absolute; top: 0px; left: 0px; width: 37px; height: 30px;">
        </div>*@
    <div class="btn-group">
        <a class="btn" data-edit="undo" title="" data-original-title="Undo (Ctrl/Cmd+Z)"><i class="fas fa-undo"></i></a>
        <a class="btn" data-edit="redo" title="" data-original-title="Redo (Ctrl/Cmd+Y)"><i class="fas fa-redo"></i></a>
    </div>
    <input type="text" data-edit="inserttext" id="voiceBtn" x-webkit-speech="" style="display: none;">
</div>
<div id="editor" contenteditable="true">

</div>

Editor.cshtml does not contain a form as I've read that a nested form is a big no no in html, so I assumed that I should wrap the outside html including the partial view in a big form and submit all of it at the same time. 
but the problem I'm having is that Model.Editor comes back as null.
how do I get around this? I'm rather new with using partial views like this. I'm more familiar with user controls in .net web forms. 
Edit: this is the controller action that creates the model object
[Authorize]
        public IActionResult EditNewsArticle(int? articleId)
        {

            dbNewsArticle article = null;
            if (articleId.HasValue && articleId.Value > 0)
            {
                article = NewsArticleData.GetArticle(articleId.Value);
            }
            NewsArticleModel model = new NewsArticleModel();
            model.ValidUntil = article?.ValidUntil ?? DateTime.Today.AddDays(7);
            model.AuthorId = article?.Author?.AccountId ?? Data.UserData.GetUserByEmail(User.Identity.Name).AccountId;
            model.Published = article?.Published ?? false;

            model.Editor = new EditorModel();

            model.ReadPermissions = new bool[5];

            if(article != null)
            {
                foreach(dbRole role in article.ReadPermissions)
                {
                    model.ReadPermissions[role.Id - 1] = true;
                }
            }

            return View(model);
        }

Edit2: to make it easier to get an overview I have pasted all the code relevant to my problem. bear in mind I usually structure and style once the functionality is working, so no need to stare yourself blind on potential ugliness

A:

Solved it myself, while not ideal, it works now. I moved this part
@Html.HiddenFor(m => m.Editor.Text, new { id = "EditorText" })

which was inside the partial view before to the outside, I have a Javascript inside the partial view which updated the value of this hidden field as soon as the html inside the div changes. this way the model that contains the editor which contans the text property does not come back as null. 
I would have preferred to keep as much as possible contained within the partial view for modularity, but I had to fix it somehow. if anyone can suggest a better solution for me, please do.

