JQuery UI Layout

Web uygulamalarında yerleşim, yazılımcının (ben) front­end bilgisi çok iyi değilse (yine ben) kabuslarından biridir. Özellikle “şu div in yüksekliğini bir türlü 100% yapamadım” dediğim zamanlar pek az değildir 🙁 Neyse ki geçen sene keşfettiğim plug­in bu konuda hayatımı kurtarmıştır.

Edinme

Bu linkten indirebileceğiniz gibi Nuget paketi olarakta edinebilirsiniz.

Kullanım

paketle gelen css ve dosyalarını referans olarak eklemek

Yerleşim planı için örnek içerik oluşturalım.

javascript ile plug­in i etkinleştirme

Görsel olarak bir takım değişiklikler yapmak gerekir ise aşağıdaki şekilde müdahale edilebilir.

Daha fazla bilgi için dökümantasyon sayfasından bilgi alabilirsiniz.

Bootsrap Panel Helper

Kullanım şekli;

@using (Html.Panel("Genel", type: PanelType.success))
{
    @Html.Editor(model => Model.Error)
    @Html.Editor(model => Model.SaltKey)
}

Panel in tipleri için enum;

public enum PanelType
{
    @default,
    success,
    info,
    danger
}

Panel i containerkap gibi kullanabilmek için ViewContext ve kapanış etiketleritag için de IDisposable dan faydalanıyoruz.

public class PanelFieldSet : IDisposable
{
    bool _disposed;
    readonly ViewContext _viewContext;
    readonly TextWriter _writer;

    public PanelFieldSet(ViewContext viewContext)
    {
        if (viewContext == null)
            throw new ArgumentNullException("viewContext");
        _viewContext = viewContext;
        _writer = viewContext.Writer;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            _disposed = true;
            _writer.Write("\t\t</div>\r\n\t</div>\r\n");
        }
    }

    public void EndDiv()
    {
        Dispose(true);
    }
}

Son olarak Html Helper a yatalık yapacak ControlHelper sınıfıclass;

public static class ControlHelper
{
    public static PanelFieldSet Panel(this HtmlHelper htmlHelper, string title, PanelType type = PanelType.@default, bool display = true, int bodyHeight = 0)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendFormat("<div class=\"panel panel-{0}\" class='{1}'>", Enum.GetName(typeof(PanelType), type), display ? "show" : "hide");
        sb.AppendFormat("<div class=\"panel-heading\">{0}</div>", title);
        sb.AppendFormat("<div class=\"panel-body\" {0}>", bodyHeight == 0 ? "" : string.Format("style='height:{0}px'", bodyHeight));
        htmlHelper.ViewContext.Writer.WriteLine(sb.ToString());
        return new PanelFieldSet(htmlHelper.ViewContext);
    }
}

JQueryUI Modal İle Mvc AJax Loader

Web uygulamalarında asenkronAsynchronous işlemler yapılırken kullanıcıya durum boyunca bilgi vermenin 500 farklı yolu mutlaka vardır. Lakin en temiz olanı, tüm ekranı kapatıp tam ortada bildirimi yapmakmış gibi gözüküyor. Bunun en büyük avantajı “istenmeyen tıklamalar” dan korunmak olarak izah edebilir.

Bunun için JQueryUI elemanWidget larından Dialog‘u kullanacağız. Hali hazırda MVC Proje Template içinde bulunduğu için işimiz gayet kolay olacak.

Queryui solution explorer

_Layout ile başlayalım;

Head içine sırası ile css ve js dosyalarını ekleyelim.

<link href="@Url.Content("~/Content/themes/base/jquery.ui.all.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery-ui-1.8.18.min.js")" type="text/javascript"></script>

Dialog açıldığında kullanıcı tarafından kapatılmasını engellemek için sağ üst köşedeki “x” kapatı işaretini kaldıralım.

<style type="text/css">
.ui-dialog-titlebar-close {
    display: none;
}
</style>

Dialog için kullanılacak div tanımını yapalım.

<div id="dialog-modal" title="Bilgilendirme">
    <p>
        <img src="/Content/images/loading.gif.jpgx" style="vertical-align: middle;" />
        işlem yapılıyor ...
    </p>
</div>

Div’ i Dialog haline getirelim.

<script type="text/javascript">
    $(function () {
        $("#dialog-modal").dialog({
            autoOpen: false,
            modal: true,
            height: 100,
            closeOnEscape: false,
            draggable: false,
            resizable: false
        });
    });
</script>

Son olarak, çağrıda bulunacak alt sayfaların da kendi script bloklarını yazacakları Section‘ı tanımlayalım.

@RenderSection("script", false)

Alt sayfalardaki script alanına iki adet fonksiyonfunction ekliyoruz. Asenkron işlem başladığında ve bittiğinde Dailog açılacak ve kapanacak.

<script type="text/javascript">
    function start() {
        $("#dialog-modal").dialog('open');
    }
    function finish() {
        $("#dialog-modal").dialog('close');
    }
</script>

AjaxOptions sınıfclass ını da tanımlarsak işlem tamamlanmış olacak.

@using (Ajax.BeginForm("Index", "Home", new AjaxOptions
{
    HttpMethod = "post",
    OnBegin = "start",
    OnSuccess = "finish"
}))

Loading gif

Mvc İle Asenkron İşlem Yapmak

Mvc uygulamalarında AsenkronAsynchronous işlem yapmak için ya Jquery yada Ajax Helper kullanmak gerekir (genelde). Jquery ile ilgili kaynak bulmak kolay iken Ajax Helper için pek de kolay değil. O yüzden bugün biraz araştırma yapma gereği hissettim.

Burada karşımıza iki adet metodçıkıyor;

  1. Ajax.ActionLink
  2. Ajax.BeginForm

Yaptıkları farklı olasada çalışma prensipleri aynı diyebilirim. Çünkü burada esas oğlan AjaxOptions sınıfı 🙂

BeginForm için basit bir örnek yapalım ve daha sonrasında ActionLink ile detaylara bakalım.

Ortak kullanım için bir sınıfclass oluşturalım;

[Serializable]
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Formu post edeceğimiz Action Method;

[HttpPost]
public string Create(Product product)
{
    //olaylar olaylar
    return "Ürün eklendi.";
}

Son olarak View formu oluşturalım;

@*Asenkron çalışması için gerekli script dosyaları*@
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/MicrosoftMvcAjax.js")" type="text/javascript"></script>
@using (Ajax.BeginForm("Create",//Controller deki metot adı
 new AjaxOptions
 {
    //form method
    HttpMethod = "post",
    //sonuç önceki ile yer değişiyor
    InsertionMode = InsertionMode.Replace,
    //işlem süresince çalışacak element id
    LoadingElementId = "loader",
    //işlem sonucunun gösterileceği element id
    UpdateTargetId = "result"
 }))
{
    <fieldset>
    <legend>Ürün</legend>
    @*Asenkron işlem sırasında kullanıcıya bilgi vermek için*@
    <div id="loader" style="display: none;">İşlem yapılıyor...</div>
    <div class="editor-label">
    Ad
    </div>
    <div class="editor-field">
    <input type="text" name="Name" />
    </div>
    <div class="editor-label">
    Fiyat
    </div>
    <div class="editor-field">
    <input type="text" name="Price" />
    </div>
    <p>
    <input type="submit" value="Ekle" />
    </p>
    @*İşlem sonucunda kullanıcıya bilgi vermek için*@
    <div id="result" style="color: maroon;"></div>
    </fieldset>
}

Peki sunucuserverdan gelecek olan veri daha karmaşık olursa ne yapacağız. Örneğin JSON formatında Product sınıfını döndürmek isteyebiliriz. İşe bu gibi durumlarda AjaxOptions unaşağıdaki özellikleriProperty ni kullanmak gerekir.

Çalışma sırasına göre;

  1. OnBegin(xhr, context)
  2. OnSuccess(result, status, xhr)
  3. OnComplete(xhr, status)
  4. OnFailure(xhr, status, error) (tabi hata olursa)

Yeni bir Action Method ekleyelim;

[HttpPost]
public JsonResult GetProduct(int Id)
{
    return Json(new Product
    {
        Id = Id,
        Name = string.Concat("Ürün ", Id),
        Price = Id * 12
    });
}

Çağrıda bulunmak için de Ajax.ActionLink kullanalım;

@Ajax.ActionLink("Ürün Detay",
"GetProduct",
new { Id = 1 },
    new AjaxOptions
    {
        HttpMethod = "post",
        OnComplete = "complete",
        OnFailure = "fail",
        OnBegin = "begin",
        OnSuccess = "success"
    })
<script type="text/javascript">
    function begin(xhr, content) {
        //olaylar
    }
    function success(result, status, xhr) {
        //olaylar
    }
    function complete(xhr, status) {
        //olaylar
    }
    function fail(xhr, status, error) {
        //olaylar
    }
</script>

İşlembaşarılı olduğunda sırası ile begin -> success -> complete fonksiyonları çalışır. Sonuçlar ise;

result
Result

status
status

xhr
xhr

Başarısız olduğunda ise begin -> fail fonksiyonları çalışır. Sonuçlar ise;

xhr
xhr

status
status

error
error