Komplexe Objekte & Arrays mit jquery $.post an einen ASP.net MVC-Controller senden

Das Szenario

Ich wollte ein komplexes Javascript-Objekt auf dem Client erzeugen und per $.post an den Server schicken. Ein einfaches Aufbauen des Objekts hat so lange funktioniert, bis ich ein Array mit weiteren Objekten erzeugt habe.

So bin ich gestartet

Mein Model auf der Serverseite sieht ungefähr so aus:

public class DataModel {
    public string Id { get; set; }
    public List<Data> Items { get; set; }
}
public class Data{
    public string[] Key { get; set; }
    public int Value { get; set; }
}

Auf dem Client habe ich dafür folgendes Aufgebaut

var data = {
    id: 'foo',
    Items: [{ Key: [ 'a', 'b' ], Value: 666 },
            { Key: [ 'c', 'd' ], Value: 999 }]
}

Nachdem ich das losgeschickt hatte, war DataModel.Id gesetzt, Items blieb NULL…

Die Lösung

jQuery ist manchmal ein…nicht ganz so nettes Ding! Ich habe viel hin und her probiert, wie ich das Model auf dem Client zusammenbauen muss, damit etwas vernünftiges auf dem Server ankommt. Dabei habe ich mich an die Notation erinnert die notwendig ist, wenn man die Daten per Form-Serialisierung versenden möchte.

Hier erhalten die Felder im name-Attribute den ‚Pfad‘, an den der Wert am Ende landen soll. Konkret heißt das, dass ein Feld, dessen Wert in DataModel.Items[0].Value stehen soll, den „name“ Items[0].Value besitzen muss.Für den Key wäre der „name“ Items[0].Key[0], Items[0].Key[1], …

Und genau SO muss dann auch der Name des Wertes im ViewModel aussehen:

var data = {
    id: 'foo' 
}
// soweit alles beim alten, jetzt das NEUE
data["Items[0].Value"] = 666;
data["Items[0].Key[0]"] = 'a';
data["Items[0].Key[1]"] = 'b';

data["Items[1].Value"] = 999;
data["Items[1].Key[0]"] = 'c';
data["Items[1].Key[1]"] = 'd';

Damit kann ich dann komplexe Daten wegschicken…

 

Wenn jemand einen besseren Weg kennt, bitte Posten! Ansonsten: Viel Spass und Erfolg damit!

 

jQuery UI Slider & Fixed Range

Ein Slider ist mit jQueryUI schnell erstellt. Schwieriger wird es erst, wenn man ihn modifizieren möchte.

Mein Problem bestand darin, einen Slider zu bauen, bei dem ein Bereich als optimal hervorgehoben werden sollte.

Ich hab mich dafür entschieden, eine Textbox mit data-Attributen zu versehen um diese dann zur Laufzeit per Javascript zu einem Slider mutieren zu lassen. Dert Wert der Textbox wird dabei als Slider-Starteinstellung genutzt.

Attribute
Name Verwendung Beispiel
data-slider Kommasepariert *1) minimaler und maximaler Wert für den Slider data-slider=“0,10″
data-sliderFixedRange Kommaseparierte *1) Werte für den hervorzuhebenden Bereich data-sliderFixedRange=“5,7″

*1: Das Trennzeichen ist über das jQuery-Plugin $dgSlider_Settings.defaults.valueSplitSign einstellbar.

Die Textbox sollte dann so aussehen:

<input type=“text“ id=“myId“ name=“myName“ data-slider=“0,10″ data-sliderFixedRange=“5,7″ />

Um aus dem Element nun einen Slider zu machen muss einfach $(‚:text[data-slider]‘).dgSlider(); aufgerufen werden.

Abschließend noch das Script:

(function($) {
$.dgSlider_Settings = {
_dataKey: ‚dgSliderDataKey‘,
defaults: {
textbox: null,
slider: null,
valueSplitSign: ‚,‘
} /* end defaults */
}

var methods = {
_init: function(settings) {
$(this).each(function() {
var $this = $(this);
var data = methods._getData($this, settings);

data.textbox = $this;
data.slider = $(„<div />“);
data.slider.insertBefore(data.textbox);
var opt = methods._createOptions(data.textbox);
data.textbox.hide();
data.slider.slider(opt);
});
},
destroy: function() {
$(this).each(function(){
var data = methods._getData($(this));
data.slider.slider(„destroy“);
data.slider.remove();
data.textbox.show();
});
},
/* Erzeugt die Options für den Slider aus den Attributen der Textbox */
_createOptions: function(textbox) {
var data = methods._getData($(this));
var sliderValues = textbox.attr(„data-slider“).split(data.valueSplitSign);
var opt = {
min: parseInt(sliderValues[0]),
max: parseInt(sliderValues[1]),
step: 1,
value: textbox.val()
};

if (textbox.attr(„data-sliderFixedRange“)) {
var fixedRange = textbox.attr(„data-sliderFixedRange“).split(data.valueSplitSign);

var startPoint = (parseInt(fixedRange[0]) * 100) / (opt.max – opt.min);
var rangeWidth = (((parseInt(fixedRange[1]) * 100) / (opt.max – opt.min)) – startPoint);

opt.create = function(evt, ui) {
var rangeDiv = $(„<div/>“).css({
position: ‚relative‘,
left: startPoint + „%“,
width: rangeWidth + „%“,
height: „100%“
}).addClass(‚bg90‘);
$(this).append(rangeDiv);
}
}
opt.change = function(evt, ui) { textbox.val(ui.value); }
return opt;
},
/* Liefert das .data-Objekt */
_getData: function(x, settings) {
var data = x.data($.dgSlider_Settings._dataKey);

if (!data) {
data = $.extend({}, $.dgSlider_Settings.defaults, settings);
x.data($.dgSlider_Settings._dataKey, data);
}
return data;
}

}

$.fn.dgSlider = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === ‚object‘ || !method) {
return methods[„_init“].apply(this, arguments);
} else {
jQuery.error(„Die Methode “ + method + “ konnte nicht gefunden werden“);
}
}

})(jQuery);

Docking Panels mit Javascript

Die Entwicklung einer Applikation für das Web stellt einen doch immer und immer wieder vor die Aufgabe eine Oberfläche zu schaffen, die vom Look and Feel her wie eine Desktop-Anwendung daherkommt.

Da wäre die immer sichtbare Toolbar oben, eine Statuszeile am unteren Rand des Browserfenster – und natürlich sollen beide beim scrollen nicht verschwinden und auch keinen Content verdecken… Das alles wäre ja noch ganz einfach mit fix positionierten DIV-Container zu realisieren, aber was, wenn die Oberfläche aussehen soll wie z.B. ein Email-Client? Oben eine Toolbar, unten eine Statuszeile, dazwischen dann links eine Navigation die 300px der Bildschirmbreite einnehemen soll, der Rest soll sich dann in einen Bereich zum auswählen von Daten, und der Detailansicht aufteilen – und natürlich den ganzen Platz des Bildschirms ausnutzen.

Wenn man sowas in VisualStudio und WinForms realisert gibt es die Möglichkeit Objekte anzudocken. Ein, zwei klicks, fertig… In HTML und JS ist das eher schwierig – es muss aber möglich gemacht werden.

Die Anforderung an meine DockPanels:

  • Ich bin nicht an eine Anzahl Panels gebunden
  • Die Größe muss sich bei einem Resize des Fensters diesem anpassen
  • Ich muss fixe und variable Höhen und Breiten definieren können

Weiterlesen