المتابعون للمدونة

الخميس، 11 أبريل 2019

صفحات ZML


صفحات ZML

قررت أن أجرب Vazor عمليا في تحويل صفحات موقع ويب مكتوبة بـ chtml إلى vbxml.

ورغم أني نجحت في تحويل الصفحات وحتى مكونات الصفحات Razor Components فقد اكتشفت عيبا كبيرا في كود vbxml وهو عدم توافقه مع مساعدات التيجان Tag Helpers في قليل ن الحالات، لكنها للأسف الحالات الأهم والأكثر فائدة!

وقد وجدت حلولا لهذه المشكلة، لكنها تتطلب تعريف خاصية إضافية في ملف كود فيجوال بيزيك، وكتابة كود طويل نسبيا في ملف vbxml يحتوي في النهاية على بعض صيغ Razor!

كل هذا يزيد من تعقيد كود الصفحة بدلا من تبسيطه، وهذا جعلني أتجه إلى حل آخر من خارج الصندوق، مبنى على تطوير فكرة قالب البيانات ForEach = "m" الذي شرحته من قبل، لكن لهدف مختلف تماما:

فقد قررت تصميم صفحات Razor بدون استخدام أي من كود فيجوال بيزيك وسي شارب!

والفكرة هنا ببساطة، أن أستخدم تيجان XML تعبر عن أوامر لغة البرمجة، ثم أترجم هذه التيجان في وقت التنفيذ إلى كود سي شارب المناظر لها، وبهذا أحصل على صفحة cshtml وأرسلها إلى Razor ليقوم بترجمتها!

وقد نفذت هذه الفكرة بالفعل، وأسميتها ZML (الحرف Z  من Razor والحرفان ML من XML) وكتبت مترجم ZML في هذا القالب.. هذا المترجم البسيط الذي كتبته في عجالة يفترض أنه يستلم صيغة ZML صحيحة بدون أخطاء (لو صار لدينا محرر كود ل ZML فسيكون هو المسئول عن تدقيق الصياغة)، وهو يتعامل حاليا مع عدد محدود من تيجان الأوامر، لكنها هي الأكثر شيوعا.. وسأضيف مزيدا من الأوامر كلما احتجت إليها عمليا بإذن الله.. وهذه الأوامر هي: 

تاج ZML
كود C# Razor الذي ينتجه
<page />
@page
<model type="mtype" />
@model mtype
<model type="List(Of mtype)" />
@model List < mtype >
<set object="obj" value="val" />
@{
      obj = val;
}
<set object="ViewData['Title']" value="Test" />
@{
      ViewData["Title"] = "Test"
}
استخدام قوسي فيجوال بيزيك:
<set object="ViewData('Message')"
        value="OK" />
@{
      ViewData["Message"] = "Ok"
}
حالة خاصة لتسهيل استخدام بيانات العرض:
Title="Test"    
                   Message="OK" />
@{
      ViewData["Title"] = "Test"
      ViewData["Message"] = "Ok"
}
<foreach var="m" in="Model">
    block of zml code
</foreach>
@foreach(var m in Model)
{
     block of zml code
}
<if condition="cond">
    block of zml code
</if>
 
@if(cond)
{
    block of zml code
}
<if condition="cond1">
    <then>
        block of zml code
    </then>
    <elseif condition="cond2">
        block of zml code
    </elseif>
   
    <else>
        block of zml code
    </else>
</if>
@if(cond1)
{
     block of zml code
 }
elseif(cond2)
{
    block of zml code
}
else
{
    block of zml code
}

 
لاحظوا أنني حاليا أستخدم ZML مع Vazor وبالتالي صار من الممكن تضمين كود ZML داخل كود vbxml كما في هذا المثال:
<zml>
    <model type="List(Of WebApp1.Student)"/>
    <h3 fff=""> Browse Students</h3>
    <p>Select from <%= Students.Count %> students:</p>
    <p>Students details:</p>
    <ul>
            <foreach var="m" in="Model">
                 <li>
                        Id: @m.Id<br/>
                        Name: @m.Name<br/>
                        <p>Grade: @m.Grade</p>
                 </li>
            </foreach>
    </ul>
</zml>
لاحظ أن كود vb المضمن داخل <%= %> لا يستخدم المعامل Model فهذا خاص فقط بصيغ ZML، وبدلا من هذا يتعامل كود فيجوال بيزيك مباشرة مع الخاصية Students المعرفة في نفس الفئة.. يمكنك تجربة هذا الكود في المشروع WebApp1 الموجود في مستودع Vazor.

سأستخدم ZML بإذن الله في تحويل كود مشروع الويب الذي ذكرته في أول الموضوع.. والجميل في الأمر أنني أستطيع أن أكتبها في صفحات cshtml مباشرة ، فكود ZML يخلو من كود فيجوال بيزيك، وبالتالي هو في نظر محرر صفحات cshtml مجرد كود XML عادي!.. لكني أتمنى أن تتبنى ميكروسوفت ZML وتنشئ له محررا خاصا بصفحات .zml حتى نحصل على الإكمال التلقائي لتيجان ZML مع فحص سلامة صياغتها.. في هذه الحالة ستستفيد مشاريع VB.NET وF# من هذا المصمم الجديد، وتكون مشكلتهما قد حلت!
هكذا ستبدو صفحة كاملة مكتوبة بـ ZML:

<page />
<model type="CatalogModel"/>
<ViewData Title="zml sample" Message="another syntax" />

<div class="container">
    <if condition="CatalogModel.CatalogItems.Any()">
        <then>
            <partial name="_pagination" for="CatalogModel.PaginationInfo" />
            <div class="esh-catalog-items row">
                <foreach var="catalog" in="CatalogModel.CatalogItems">
                    <div class="esh-catalog-item col-md-4">
                        <partial name="_product" for="@catalog" />
                    </div>
                </foreach>
            </div>
            <partial name="_pagination" for="CatalogModel.PaginationInfo" />
        </then>
        <elseif condition="CatalogModel.Count>3">
           
        </elseif>
        <else>
            <div class="esh-catalog-items row">
                THERE ARE NO RESULTS THAT MATCH YOUR SEARCH
            </div>
        </else>
    </if>
</div>
وهذا هو كود cshtml المناظر لها:

@page
@model CatalogModel
@{
    ViewData["Title"] = "zml sample";
    ViewData["Message"] = "another syntax";
}
<div class="container">
    @if (@Model.CatalogModel.CatalogItems.Any())
    {
        <partial name="_pagination" for="CatalogModel.PaginationInfo" />

        <div class="esh-catalog-items row">

            @foreach (var catalog in @Model.CatalogModel.CatalogItems)

            {

                <div class="esh-catalog-item col-md-4">

                    <partial name="_product" for="@catalog" />

                </div>

            }

        </div>

        <partial name="_pagination" for="@Model.CatalogModel.PaginationInfo" />

    }

    elseif (CatalogModel.Count > 3)

    {

   

    }

    else

    {

    <div class="esh-catalog-items row">

        THERE ARE NO RESULTS THAT MATCH YOUR SEARCH

    </div>

    }

</div>

 

 

 

 

ليست هناك تعليقات:

إرسال تعليق

ملحوظة: يمكن لأعضاء المدونة فقط إرسال تعليق.

صفحة الشاعر