2013-01-08 120 views
1

让我们先从代码..淘汰赛复杂的数据模型绑定

的JavaScript绑定视图模型,并显示对话框

$("#add-song").click(function() { 
    $("<div>") 
     .attr("data-bind", "template: { name: 'manage-song-template' }") 
     .dialog({ 
      resizable: false, 
      modal: true, 
      title: "Add Song", 
      width: 960, 
      height: 490, 
      buttons: [ 
       { 
        text: "Create Song", 
        'data-bind': 'click: savechanges', 
        click: function() { 

        } 
       }, 
       { 
        text: "Close", 
        click: function() { 
         $(this).dialog("close"); 
        } 
       } 
      ], 
      close: function() { 
       $(this).dialog('destroy').remove(); 
      }, 
      open: function() { 
       ko.applyBindings(new my.managesongviewmodel()); 
       jquerybindings(); 
      } 
     });   
}); 

现在让我们来看看视图模型

my.managesongviewmodel = function() { 
    var 
     //Scalar Properties 
     song = null, 

     //Functions 
     loadfromserver = function (Id) { 
      $.post("/song/getsong", "id=1", function (response) { 
       if (response.Success) { 
        var data = response.Data; 
        var song = response.Data.Song; 

        var songdata = { 
         Song: { 
          Id: song.Id, 
          Title: song.Title, 
          Description: song.Description, 
          Lyrics: song.Lyrics, 
          isMaster: song.isMaster, 
          AudioFilePath: song.AudioFilePath, 
          CoverImageFilePath: song.CoverImageFilePath, 
          CreatedDate: song.CreatedDate 
         }, 
         Genres: data.Genres, 
         SongAlternateTitles: data.SongAlternateTitles, 
         Exploitations: data.Exploitations, 
         SongWriterSongs: data.SongWriterSongs 
        };       
        song = new my.song(songdata); 
        alert(song.title()); 
       } 
      }); 
     }, 

     savechanges = function() { 
     }; 

    loadfromserver(); 
    return { 
     song: song, 
     loadfromserver: loadfromserver 
    }; 
}; 

my.song = function (data) { 
    var 
     //Scalar Properties 
     id = ko.observable(data.Song.Id), 
     title = ko.observable(data.Song.Title), 
     description = ko.observable(data.Song.Description), 
     lyrics = ko.observable(data.Song.Lyrics), 
     ismaster = ko.observable(data.Song.isMaster), 
     audiofilepath = ko.observable(data.Song.AudioFilePath), 
     coverimagefilepath = ko.observable(data.Song.CoverImageFilePath), 
     createddate = ko.observable(data.Song.CreatedDate), 

     //Arrays 
     genres = ko.observableArray(data.Genres), 
     alttitles = ko.observableArray(data.SongAlternateTitles), 
     exploitations = ko.observableArray(data.Exploitations), 
     songwritersongs = ko.observableArray(data.SongWriterSongs); 

    return { 
     id: id, 
     title: title, 
     description: description, 
     lyrics: lyrics, 
     ismaster: ismaster, 
     audiofilepath: audiofilepath, 
     coverimagefilepath: coverimagefilepath, 
     createddate: createddate, 

     genres: genres, 
     alttitles: alttitles, 
     exploitations: exploitations, 
     songwritersongs: songwritersongs 
    }; 
}; 

这里是我的模板

<script type="text/html" id="manage-song-template"> 
    <div class="modal-form"> 
     <span data-bind="text: song.title"></span> 
    </div> 
</script> 

Chrome抛出错误“Can not read property'title'of null;”当我启动对话框时。也就是说,“alert(song.title());”实际上显示了歌曲标题。

有关我哪里出错的想法吗?

更新

我已经创建了一个复制问题的jsfiddle。 http://jsfiddle.net/mcottingham/H7jqa/28/

+1

这ISN”因为绑定在AJAX调用完成之前发生,所以不起作用。 –

回答

5

这很容易。在你显示模式窗口的那一刻,你的歌曲var仍然等于null。所以,你必须等待约歌曲信息从服务器加载:

$("<div>").attr("data-bind", "template: { name: 'manage-song-template' }").dialog({ 
    // another options 
    open: function (event, ui) { 
    var vm = new my.managesongviewmodel(), domNode = this; 
    vm.loadfromserver().done(function() { 
     ko.applyBindings(vm, domNode); 
     jquerybindings(); 
    }); 
    } 
}) 

//另一代码

而在loadfromserver函数的开头添加return声明:

loadfromserver = function (Id) { 
    return $.post("/song/getsong", "id=1", function (response) { 
    // code 
    }); 
} 
+0

正是我输入的答案。 +1以正确处理jqxhr对象。 – jjperezaguinaga

+0

此外,作为代码改进,您可以用'ko.applyBindingsToNode(domNode,{template:{name:'manage-song-template'}})'替换'ko.applyBindings(vm,domNode)'。然后你也可以移除'attr('data-bind',...)'方法的调用。这种改变使你的代码更快更优雅 – Serjio

+0

@Serjio我已经提出了修改,但是,我仍然得到相同的错误。警报仍显示标题文本。 – mcottingham