Blog專案 - 創造文章
2020-09-20 01:27 155

上一篇文章做到的進度是:

能讀DB抓文章進Views
能根據傳進Views的Data產生文章列表
能點進去看內文

那基本上Blog最最基礎的部份就達成了,接下來應該開始寫文章,不然其他功能都用不到

當初計劃本站的時候是打算把文章用markdown語法儲存在DB
再找方法把markdown parse成html顯示出來
所以blog table的欄位也寫明是markdown_content


首先要有一個Blog Create的頁面
新增View Controller這些就不再詳述了
總之我們有一個Controller,裡面有一個Method會接收GET request,return 新增的Create.cshtml這個view
另外有一個Method是接收POST request,會把傳來的blog object寫進DB。
Create.cshtml長這樣:
 

@model Blog
@{
}
<head>
    @*<script src="https://cdn.ckeditor.com/ckeditor5/22.0.0/classic/ckeditor.js"></script>*@
    @if (TempData["Message"] != null)
    {
        <script type="text/javascript">
        var message = @Html.Raw(Json.Serialize(TempData["Message"]));
        alert(message);
        </script>
    }
</head>
<h2>Create Blog</h2>
<div id="blogBody" class="col-md-9 col-sm-12 col-12 bottom">
    <p>@TempData["ip"]</p>
    <form action="/Blog/Create")" method="post">
        <div class="form-group">
            <label class="col-md-2" asp-for="Title" for="title">Title</label>
            <input class="col-md-8" asp-for="Title" type="text" name="title" id="title" />
            <span asp-validation-for="Title" class="text-danger col-md-1 small"></span>
        </div>
        <div class="form-group">
            <label class="col-md-2" asp-for="Category" for="category">Category</label>
            <input class="col-md-8" asp-for="Category" type="text" name="Category" id="category" />
            <span asp-validation-for="Category" class="text-danger col-md-1 small"></span>
        </div>
        <div class="form-group">
            <label class="col-md-2" asp-for="Tags" for="tags">Tags</label>
            <input class="col-md-8" asp-for="Tags" type="text" name="tags" id="tags" />
            <span asp-validation-for="Tags" class="text-danger col-md-1 small"></span>
        </div>
        <div class="form-group">
            <label class="col-md-2" asp-for="Password" for="password">Password</label>
            <input class="col-md-4" asp-for="Password" type="password" name="password" value="" id="password" />
            <span asp-validation-for="Password" class="text-danger col-md-1 small"></span>
        </div>
        <div class="form-group">
            <label class="col-md-2" asp-for="NoComment" for="noComment">No Comment</label>
            <input class="col-md-1" asp-for="NoComment" type="checkbox" name="no_Comment" id="noComment" />
            <span asp-validation-for="NoComment" class="text-danger col-md-1 small"></span>
        </div>
        <div class="form-group">
            <label class="col-md-2" asp-for="NoRobots" for="noRobots">No Robots</label>
            <input class="col-md-1" asp-for="NoRobots" type="checkbox" name="no_Robots" id="noRobots" />
            <span asp-validation-for="NoRobots" class="text-danger"></span>
        </div>
        <div class="form-group">
            <label class="col-md-2" for="content" style="vertical-align:top">Content</label>
            <textarea class="col-md-8" name="markdown_Content" id="content" style="height:500px"></textarea>
            <script src="~/lib/ckeditor/ckeditor.js"></script>
            <script>
                // Replace the <textarea id="editor1"> with a CKEditor 4
                // instance, using default configuration.
                var editor = CKEDITOR.replace('content');
            </script>
            @if (ViewData["EditMode"] != null && (Boolean)ViewData["EditMode"])
            {
                <script>
                    editor.on('instanceReady', function () {
                        editor.insertHtml(`@Html.Raw(Model.Markdown_Content)`);
                    });
                </script>
            }

            @*below querySelector('#content') meant replace the element of id="content"*@
            @*
            <script>

                ClassicEditor
                    .create(document.querySelector('#content'), {
                        codeBlock: {
                            languages: [{ language: 'cs', label: 'C#' },
                                { language: 'cpp', label: 'C++' },
                                { language: 'css', label: 'CSS' },
                                { language: 'html', label: 'HTML' },
                                { language: 'java', label: 'Java' },
                                { language: 'javascript', label: 'JavaScript' },
                                { language: 'python', label: 'Python' }]
                        }
                    })
                    .catch(error => {
                        console.error(error);
                    });
            </script>
            *@
        </div>
        <hr style="border-top:1px solid #eee" />
        <input type="submit" value="Submit" class="btn btn-default" style="border:1px solid black;" />
        

    </form>
</div>
<partial name="~/Views/Shared/_sidebar.cshtml" />

很長的一段...
所以以下會有詳解
 

<form action="/Blog/Create" method="post">
    <div class="form-group">
        <label class="col-md-2" asp-for="Title" for="title">Title</label>
        <input class="col-md-8" asp-for="Title" type="text" name="title" id="title" />
        <span asp-validation-for="Title" class="text-danger col-md-1 small"></span>
    </div>
    .
    .
    .
    <div class="form-group">
        <label class="col-md-2" for="content" style="vertical-align:top">Content</label>
        <textarea class="col-md-8" name="markdown_Content" id="content" style="height:500px"></textarea>
    </div>
    <input type="submit" value="Submit" class="btn btn-default" style="border:1px solid black;" />
</form>

Create頁面內主要目的是填入一個blog所需的一切資料,然後POST到某個url去
<form>的用途就是負責POST的動作
form裡面有好幾組<label>和<input>,label如其名只是一個文字標籤,當中的for是指這個label是哪個id的label,asp-for則指向它屬於model內的哪一個property。<span>使用了asp-validation-for,當表單輸入資料有誤時,這個span會顯示錯誤文字
當我們按下Submit時,所有input的value都會被封進POST request內傳送出去,詳情可以看下面:
https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data
 

<div class="form-group">
    <label class="col-md-2" for="content" style="vertical-align:top">Content</label>
    <textarea class="col-md-8" name="markdown_Content" id="content" style="height:500px"></textarea>
    <script src="~/lib/ckeditor/ckeditor.js"></script>
    <script>
        // Replace the <textarea id="editor1"> with a CKEditor 4
        // instance, using default configuration.
        var editor = CKEDITOR.replace('content');
    </script>
    @*below querySelector('#content') meant replace the element of id="content"*@
    @*
    <script>

        ClassicEditor
            .create(document.querySelector('#content'), {
                codeBlock: {
                    languages: [{ language: 'cs', label: 'C#' },
                        { language: 'cpp', label: 'C++' },
                        { language: 'css', label: 'CSS' },
                        { language: 'html', label: 'HTML' },
                        { language: 'java', label: 'Java' },
                        { language: 'javascript', label: 'JavaScript' },
                        { language: 'python', label: 'Python' }]
                }
            })
            .catch(error => {
                console.error(error);
            });
    </script>
    *@
</div>

Blog的markdown_content,由一個textarea的值輸入。
我們當初預期blog的內容是由markdown語法轉化html而成,裡面應可包含圖片、文字、超連結等內容,這很明顯不是一個textarea足以處理的,我們需要一個多功能的文本編輯器,如同microsoft word一樣。這裡用上CKEditor,引用在官網下載的js,執行script,替換id為content的textarea,這個插件可以提供超級豐富的文檔編輯功能,比如格式、插入圖片、插入youtube連結、emoji還有很多很多不同的選用功能,並且最後輸出成Html格式。
由於太好用,所以最後欄位還是叫markdown_content,但實際上是html,我也爛得改。
最後沒有使用CKEditor 5的原因是,它太新,插件不足。

總結一下,我們新增了一個Create blog的頁面,裡面有一個form,包含了blog物件的大部份所需欄位,比如title、content等,並且引入了CKEditor作為編輯器,寫好文章後按submit,form的各種input打包成post request的body,發出POST request到/Blog/Create,Controller的Method收到這個POST request後就會從後台找相關class把Post request的body(即blog)寫進DB,最後回到首頁便能看到相關文章。

Category: Coding
Tags: Side Project