I have a checkbox dropdown in a function. So the user can select one, more than one or zero. When the user select one or more than one, everything is correct. But when the user dont select any I have a null pointer exception. To handle this exception I want to make by default that if he doesnt select anything to show the results of all (like if he is selecting all). How can I do that?
Here is the JS function
$(function () {
$("#datepicker").datepicker({
//defaultDate: "+1w",
changeMonth: true,
changeYear: true,
numberOfMonths: 1,
minDate: "01/01/2008"
})
.datepicker('setDate', new Date());
$("button.action").click(function () {
//var users = new Array();
var date = $('#datepicker').val().toString();
var selected_values = new Array();
//var userName = $(' .checked:checked').val();
$(document).ready(function () {
selected_values = []; // initialize empty array
$(".checked:checked").each(function () {
selected_values.push($(this).val());
});
});
$.ajax({
url: 'EmployeeDate',
datatype: "application/json",
traditional:true,
data: {
lstUserName: selected_values,
strDate: date
},
success: function (data, textStatus, jqXHR) {
$('#DataUser').html(data);
},
error: function () {
console.log("error handler when ajax request fails... ");
},
});
});
});
and this is the controller:
public IEnumerable<DateTime> getInfoByDate(string strDate, string[] lstUserName)
{
CareDB context = new CareDB();
IEnumerable<DateTime> lst = null;
List<DateTime> model = new List<DateTime>();
if (lstUserName != null)
{
foreach (string user in lstUserName)
{
SqlParameter userName = new SqlParameter("#EmployeeName", user);
SqlParameter Date = new SqlParameter("#Date", strDate);
object[] parameters = new object[] { Date, userName };
model.Add(context.ReleaseDate.SqlQuery("_UserInformationByDate #Date, #EmployeeName", parameters).ToList().FirstOrDefault());
}
}
else
{
SqlParameter Date = new SqlParameter("#Date", strDate);
SqlParameter userName = new SqlParameter("#EmployeeName", lstUserName);
object[] parameters = new object[] { Date, userName };
model = context.ReleaseDate.SqlQuery("_UserInformationByDate #Date, #EmployeeName", parameters).ToList();
}
context.Dispose();
context = null;
return model;
}
Try this
$(document).ready(function () {
selected_values = []; // initialize empty array
// nothing selected so push all value regadless
if( $(".checked:checked").length == 0)
{
$(".checked").each(function () {
selected_values.push($(this).val());
});
}
else
{
$(".checked:checked").each(function () {
selected_values.push($(this).val());
});
});
}
Related
I refer this tutorial https://github.com/bhrugen/AppointmentScheduler
I did same code but I'm not able to show Get Calendar Data when I running it, It's shows error - Unable to cast object of type 'System.String' to type 'System.Boolean.
My Code is :-
AppointmentApiController.cs :
[HttpGet]
[Route("GetCalendarData")]
public IActionResult GetCalendarData(string doctorId)
{
CommonResponse<List<AppointmentVM>> commonResponse = new CommonResponse<List<AppointmentVM>>();
try
{
if (role == Helper.Patient)
{
commonResponse.dataenum = _appointmentService.PatientsEventsById(loginUserId);
commonResponse.status = Helper.success_code;
}
else if (role == Helper.Doctor)
{
commonResponse.dataenum = _appointmentService.DoctorsEventsById(loginUserId);
commonResponse.status = Helper.success_code;
}
else
{
commonResponse.dataenum = _appointmentService.DoctorsEventsById(doctorId);
commonResponse.status = Helper.success_code;
}
}
catch (Exception e)
{
commonResponse.message = e.Message;
commonResponse.status = Helper.failure_code;
}
return Ok(commonResponse);
}
Script.js :
var routeURL = location.protocol + "//" + location.host;
$(document).ready(function () {
$("#appointmentDate").kendoDateTimePicker({
value: new Date(),
dateInput: false
});
InitializeCalendar();
});
var calendar;
function InitializeCalendar() {
try {
var calendarEl = document.getElementById('calendar');
if (calendarEl != null) {
calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
headerToolbar: {
left: 'prev,next,today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
selectable: true,
editable: false,
select: function (event) {
onShowModal(event, null);
},
eventDisplay:'block',
events: function (frtch, successCallback, failureCallback) {
$.ajax({
url: routeURL + '/api/Appointment/GetCalendarData?doctorId=' + $("#doctorId").val(),
type: 'GET',
dataType: 'JSON',
success: function (response) {
var events = [];
if (response.status === 1) {
$.each(response.dataenum, function (i, data) {
events.push({
title: data.title,
description: data.description,
start: data.startDate,
end: data.endDate,
backgroundColor: "#162466",
textColor: "white",
id: data.id
});
})
}
successCallback(events);
},
error: function (xhr) {
$.notify("Error", "error");
}
});
},
eventClick: function (info) {
getEventDetailsByEventId(info.event);
}
});
calendar.render();
}
}
catch (e) {
alert(e);
}
}
AppointmentService.cs :
public List<AppointmentVM> DoctorsEventsById(string doctorId)
{
return _db.Appointments.Where(x => x.DoctorId == doctorId).ToList().Select(c => new AppointmentVM()
{
Id = c.Id,
Description = c.Description,
StartDate = c.StartDate.ToString("yyyy-MM-dd HH:mm:ss"),
EndDate = c.EndDate.ToString("yyyy-MM-dd HH:mm:ss"),
Title = c.Title,
Duration = c.Duration,
IsDoctorApproved = c.IsDoctorApproved
}).ToList();
}
IAppointmentService.cs :
public List<AppointmentVM> DoctorsEventsById(string doctorId);
Unable to cast object of type 'System.String' to type 'System.Boolean.
You need to make sure the type of IsDoctorApproved in AppointmentVM is bool:
public class AppointmentVM
{
public bool IsDoctorApproved {get;set;}
}
Also,you need to make sure the type of IsDoctorApproved in your database is bool.
I have an jsp page where the user select between two dates. I need validation to ensure that the limit of the range is a month. I need to display message for error handling about that issue.
I tried making a function with return true and false. When the return is false, the message is already appears but system is still running to the next step. Here is my jsp page: (I use netbeans editor)
var fromDate = new Date(document.getElementById("fromTgl").value);
var toDate = new Date(document.getElementById("toTgl").value);
//call the function
var validateDate;
validateDate = rangeWithinDates(toDate,fromDate);
//funtion for validation within two dates
function rangeWithinDates(toDate,fromDate){
var diff = Math.abs(toDate.getTime() - fromDate.getTime());
var daysDiff = diff / (1000 * 60 * 60 * 24);
if (daysDiff>30){
window.alert("Please limit the date range to 1 month!");
return false;
} else {
return true;
}
}
it's my full script
<script>
var officeCode;
var fdsReport;
var rows;
$(document).ready(function() {
esLoadingAnimWindow("wndLoading");
/** Get the userId from session scope **/
var userId = "${sessionScope.UserSession.getUserId()}";
var CurrOfficeCode = "${sessionScope.UserSession.getUserOfficeCode()}";
if ($("#officeCode").data("kendoDropDownList") == null) {
$('#officeCode').kendoDropDownList({
dataTextField: "nameShort",
dataValueField: "officeCode",
dataSource: {
transport: {
read: {
dataType: "json",
url: getFormRestUrl() + "/getListOffice?officeCode=" + CurrOfficeCode
}
}
},
optionLabel: "Select Office Code"
});
}
if($("#fromTgl").data("kendoDatePicker")==null) {
$("#fromTgl").kendoDatePicker({value: new Date(), format: "dd MMMM yyyy"});
}
if($("#toTgl").data("kendoDatePicker")==null) {
$("#toTgl").kendoDatePicker({value: new Date(), format: "dd MMMM yyyy"});
}
$("#wndLoading").kendoWindow({
actions: ["Close"],
modal: true,
width: "350px",
resizable: false,
title: false,
draggable: false,
open: function(e) { $("html, body").css("overflow", "hidden"); },
close: function(e) {
$("html, body").css("overflow", "");
}
}).data("kendoWindow");
// Call the function to stop scrolling main window when scrolling the content of kendo dropdownlist.
stopScroll($("#officeCode").data("kendoDropDownList").ul.parent());
});
$("#btnProcess").click(function(e){
e.preventDefault();
$("#wndLoading").data("kendoWindow").center().open();
var fromDate = new Date(document.getElementById("fromTgl").value);
var toDate = new Date(document.getElementById("toTgl").value);
var validateDate;
validateDate = rangeWithinDates(toDate,fromDate);
fdsReport = new kendo.data.DataSource({
transport: {
read: {
url: getFormRestUrl() + "/getReportFidusia?officeCode=" + $("#officeCode").val().trim()
+ '&beginDate=' + dateToString($("#fromTgl").data("kendoDatePicker").value())
+ '&endDate=' + dateToString($("#toTgl").data("kendoDatePicker").value()),
dataType: "json",
contentType: "application/json"
}
}
});
rows = [{
cells:[
{ value: "TN NY NN" },
{ value: "Pemberi Fidusia" },
{ value: "Pekerjaan" },
{ value: "Kota Lahir" },
{ value: "Tanggal Lahir" }
]
}];
fdsReport.read().then(function(){
var data = fdsReport.data();
for (var i = 0; i < data.length; i++){
rows.push({
cells: [
{ value: data[i].tNnYnN},
{ value: data[i].pemberiFidusia},
{ value: data[i].jobCust},
{ value: data[i].kotaLahir},
{ value: data[i].tglLahir.slice(0,4) + "-" + data[i].tglLahir.slice(5,7) + "-" + data[i].tglLahir.slice(8,10)}
]
});
};
var workbook = new kendo.ooxml.Workbook({
sheets: [
{
columns: [
{ autoWidth: true },
{ autoWidth: true },
{ autoWidth: true },
{ autoWidth: true },
{ autoWidth: true }
],
title: "Laporan Fidusia",
rows: rows
}
]
});
$("#wndLoading").data("kendoWindow").close();
// Save the file as Excel file with extension xlsx
kendo.saveAs({
dataURI: workbook.toDataURL(),
fileName: "erpt_laporan_fidusia.xlsx"
});
});
});
//Ajax error listener
$(document).ajaxError(function (event, jqxhr, settings, thrownError){
//Close the loading window if it is opened
$("#wndLoading").data("kendoWindow").close();
//Open the alert window.
var wndAlert = registerAlertModalWindow("wndAlert", jqxhr.responseText);
wndAlert.center().open();
});
function getGLobalRestUrl() {
return "/easy/api";
}
function getFormRestUrl() {
return getGLobalRestUrl() + "/OMTRNF661";
}
function dateToString(pDate) {
return kendo.toString(pDate, 'yyyy-MM-dd').trim();
}
function rangeWithinDates(toDate,fromDate){
var diff = Math.abs(toDate.getTime() - fromDate.getTime());
var daysDiff = diff / (1000 * 60 * 60 * 24);
if (daysDiff>30){
window.alert("Please limit the date range to 1 month!");
document.getElementById("toTgl").value = "";
return false;
}
return true;
}
</script>
the result of this code
I expect if return false will display an error message and stop the running. so, the users must choose the date according to predetermined range. And if return true will be continue to the next step. Please help me to resolve this..
Your validateDate doesn't prevent you from downloading: it's just an unused boolean.
If you want to, you'll have to do something like this:
if (validateDate){<the rest of your download code section>}
You can reset textbox value to empty and ask user to enter the value again. You can reset only last date value or both.
if (daysDiff>30){
window.alert("Please limit the date range to 1 month!");
document.getElementById("toTgl").value = "";
return false;
}
return true;
In file downloading function check the value true or false
if (validateDate == true){
// your code
}
I have been reading ALL of the documentation on this and I still cannot get it to work.
I have a Web API which provides a JSON object. It's a list of 22 things. Just 22 lines of text.
I want to take these and form a TreeView. Each of these 22 strings will have items under them but I just want to get the first part working.
My first question is, how do I extract data from an API and populate a treeView with it?
On my main page, I have this:
<div id="treeView"></div>
On my JavaScript file I have this:
$("#treeView").kendoTreeView({
checkboxes: true,
dataSource: {
transport: {
read: {
url: "http://...",
dataType: "json"
}
}
}
});
When I try to run the page, I get "Request failed." [Retry]
If I open up a browser and go to this URL, data is returned fine as a JSON object.
What am I doing wrong here?
EDIT -
Code that is returning the JSON:
public List<string> getNotificationByUser(int id)
{
List<string> notificationTitles = new List<string>();
foreach (var notification in notifications)
{
notificationTitles.Add(notification.ToString());
}
return notificationTitles;
}
Ok! I've been able to reproduce your error. The question is that 22 lines of text are not a valid JSON.
Returning something like:
This
is
a
test
Is not a valid JSON.
But a valid JSON is not enough, you should return something like this:
[
{ "text": "This" },
{ "text": "is" },
{ "text": "a" },
{ "text": "test" }
]
I.e.: The result should be an array of objects where each object has a text field.
NOTE I know that it does not have to be called text but for simplicity I used it since it is the default value.
I figured out all of my answers:
function CreateNotificationTree(userId)
{
debugger;
var data = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: "../api/notifications/byuserid/" + userId,
contentType: "application/json"
}
},
schema: {
model: {
children: "notifications"
}
}
});
$("#treeview").kendoTreeView({
dataSource: data,
loadOnDemand: true,
dataUrlField: "LinksTo",
checkboxes: {
checkChildren: true
},
dataTextField: ["notificationType", "NotificationDesc"],
select: treeviewSelect
});
function treeviewSelect(e)
{
var node = this.dataItem(e.node);
window.open(node.NotificationLink, "_self");
}
}
[HttpGet]
public List<Node> getNotifications(int id)
{
var bo = new HomeBO();
var list = bo.GetNotificationsForUser(id);
var notificationTreeNodes = (from GBLNotifications n in list
where n.NotificationCount != 0
select new NotificationTreeNode(n)).ToList();
var li = notificationTreeNodes.Select(no => new Node
{
notificationType = no.NotificationNode.NotificationType + " " + "(" + no.NotificationNode.NotificationCount + ")", notifications = bo.GetNotificationsForUser(id, no.NotificationNode.NotificationTypeId).Cast<GBLNotifications>().Select(item => new Notification
{
ID = item.NotificationId, NotificationDesc = item.NotificationDescription, Params = new List<NotificationParam>
{
new NotificationParam
{
ParamName = item.Param1, ParamVal = item.ParamValue1
},
new NotificationParam
{
ParamName = item.Param2, ParamVal = item.ParamValue2
},
new NotificationParam
{
ParamName = item.Param3, ParamVal = item.ParamValue3
},
new NotificationParam
{
ParamName = item.Param4, ParamVal = item.ParamValue4
},
new NotificationParam
{
ParamName = item.Param5, ParamVal = item.ParamValue5
},
},
ActionPageName = item.ActionPageName
}).ToList()
}).ToList();
li.ForEach(i => i.notifications.ForEach(x => x.SetNotificationLink()));
return li;
}
How do I force a popup page to post to its controller first before posting to the parent controller? The popup page is setting up some session variables that would be used in the parent page. When the user double click on the grid on the pop-up page, it goes directly to the parent controller instead of going to the child controller.
Here is the parent where the popup is being called
//Javascript to open the popup window
#using (Html.BeginForm("Student", "StudentPage", FormMethod.Get, new { onsubmit = "", id = "student" }))
{
//where the popup window is located
}
Here is the popup form:
#using (Html.BeginForm("Index", "StudentInformation", FormMethod.Post, new {id="StudentSearchForm"}))
{
#(Html
.Telerik()
.Grid((IEnumerable<OverrideStudent>)SessionWrapper.Student.OtherStudentSelected)
.Name("StudentData")
.DataKeys(Keys =>
{
Keys.Add(c => c.StudentID);
})
.DataBinding(databinding => databinding.Server())
.Columns(columns =>
{
columns.Bound(p => p.StudentId)
.Title("Student ID")
.Width(15)
.Sortable(true)
.Filterable(false);
columns.Bound(p => p.StudentDescription)
.Title("Description")
.Width(65)
.Sortable(true)
.Filterable(false);
columns.Command(command =>
{
command.Custom("AddStudent")
.Text("Select")
.DataRouteValues(routes =>
{
routes.Add(o => o.StudentID).RouteKey("StudentID");
routes.Add(o => o.StudentDescription).RouteKey("StudentDescription");
})
.Action("Student", "StudentInfo");
.HtmlAttributes(new { onclick = "PostData(this);StudentSelectClick(this)" });
}).Width(20);
}).ClientEvents(clients => clients
.OnComplete("OnComplete")
//.OnDataBinding("DataBinding")
//.OnDataBound("onRowDataBound")
.OnRowSelected("StudentDoubleClick")
)
.Sortable()
.Selectable()
.Filterable(filtering => filtering
.Enabled(true)
.Footer(true)
.HtmlAttributes(new { style = "padding-right: 0.0em;" }))
}
//This is the script that handles that double click:
function StudentDoubleClick(e) {
var fromCourse = "#SessionWrapper.Student.FromCoursePage";
var fromList = "#SessionWrapper.Student.FromListingPage";
if (fromCourse == "True") {
$('tr', this).live('dblclick', function () {
alert("Inside TR count = " + count);
count = count + 1;
DoSearchStudent(e);
});
}
if (fromList == "True") {
$('tr', this).live('dblclick', function () {
DoSearchStudent(e);
});
}
}
function DoSearchStudent(e) {
var row = e.row;
var StudentID = row.cells[0].innerHTML;
var StudentDescription = row.cells[1].innerHTML;
// alert(procCodeDesc);
var data = { "StudentID": StudentID, "StudentDescription": StudentDescription, "action": "Double Click" };
var url = '#Url.Action("Student", "StudentInfo")';
$.ajax({
url: url,
type: 'post',
dataType: 'text',
cache: false,
async: false,
data: data,
success: function (data) {
window.top.location.href = window.top.location.href;
},
error: function (error) {
alert("An error has occured and the window will not be closed.");
}
});
}
//This is the controller that I need to go to first
public class StudentInfoController : Controller
{
.......
public string Student(string StudentID, string StudentDescription, string action)
{
if (StudentDescription != null)
{
StudentDescription = HttpUtility.HtmlDecode(StudentDescription);
}
try
{
RedirectToAction("AddStudent", "StudentInfo", new { StudentID = StudentID, StudentDescription = StudentDescription, action = action });
}
catch (Exception e)
{
return "Error " + e.ToString();
}
return "Success";
}
}
After the double click, it goes directly to the controller below instead. AS a result, my variables are not being set resulting in null exception.
public class StudentPageController : Controller
{
.......
public string Student(string StudentID, string StudentDescription, Student Students)
{
...........
}
}
It was a timing issue. When the user close the popup window, the popup thread is not done executing. At the same time, another thread starts to run, and not all the session variables are set as of yet. Before closing the popup window, I added a 1 second delay.
setTimeout('StudentWindow.close()', 1000);
I've just started using Backbone.js and my test cases are churning up something pretty weird.
In short, what I am experiencing is -- after I call a Backbone Model's constructor, some of the fields in my object seem to come from a previously item. For instance, if I call:
var playlist = new Playlist({
title: playlistTitle,
position: playlists.length,
userId: user.id
});
playlist.get('items').length; //1
however if I do:
var playlist = new Playlist({
title: playlistTitle,
position: playlists.length,
userId: user.id,
items: []
});
playlist.get('items').length; //0
Here's the code:
define(['ytHelper', 'songManager', 'playlistItem'], function (ytHelper, songManager, PlaylistItem) {
'use strict';
var Playlist = Backbone.Model.extend({
defaults: {
id: null,
userId: null,
title: 'New Playlist',
selected: false,
position: 0,
shuffledItems: [],
history: [],
items: []
},
initialize: function () {
//Our playlistItem data was fetched from the server with the playlist. Need to convert the collection to Backbone Model entities.
if (this.get('items').length > 0) {
console.log("Initializing a Playlist object with an item count of:", this.get('items').length);
console.log("items[0]", this.get('items')[0]);
this.set('items', _.map(this.get('items'), function (playlistItemData) {
var returnValue;
//This is a bit more robust. If any items in our playlist weren't Backbone.Models (could be loaded from server data), auto-convert during init.
if (playlistItemData instanceof Backbone.Model) {
returnValue = playlistItemData;
} else {
returnValue = new PlaylistItem(playlistItemData);
}
return returnValue;
}));
//Playlists will remember their length via localStorage w/ their ID.
var savedItemPosition = JSON.parse(localStorage.getItem(this.get('id') + '_selectedItemPosition'));
this.selectItemByPosition(savedItemPosition != null ? parseInt(savedItemPosition) : 0);
var songIds = _.map(this.get('items'), function(item) {
return item.get('songId');
});
songManager.loadSongs(songIds);
this.set('shuffledItems', _.shuffle(this.get('items')));
}
},
//TODO: Reimplemnt using Backbone.sync w/ CRUD operations on backend.
save: function(callback) {
if (this.get('items').length > 0) {
var selectedItem = this.getSelectedItem();
localStorage.setItem(this.get('id') + '_selectedItemPosition', selectedItem.get('position'));
}
var self = this;
console.log("Calling save with:", self);
console.log("my position is:", self.get('position'));
$.ajax({
url: 'http://localhost:61975/Playlist/SavePlaylist',
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(self),
success: function (data) {
console.log('Saving playlist was successful.', data);
self.set('id', data.id);
if (callback) {
callback();
}
},
error: function (error) {
console.error("Saving playlist was unsuccessful", error);
}
});
},
selectItemByPosition: function(position) {
//Deselect the currently selected item, then select the new item to have selected.
var currentlySelected = this.getSelectedItem();
//currentlySelected is not defined for a brand new playlist since we have no items yet selected.
if (currentlySelected != null && currentlySelected.position != position) {
currentlySelected.set('selected', false);
}
var item = this.getItemByPosition(position);
if (item != null && item.position != position) {
item.set('selected', true);
localStorage.setItem(this.get('id') + '_selectedItemPosition', item.get('position'));
}
return item;
},
getItemByPosition: function (position) {
return _.find(this.get('items'), function(item) {
return item.get('position') == position;
});
},
addItem: function (song, selected) {
console.log("this:", this.get('title'));
var playlistId = this.get('id');
var itemCount = this.get('items').length;
var playlistItem = new PlaylistItem({
playlistId: playlistId,
position: itemCount,
videoId: song.videoId,
title: song.title,
relatedVideos: [],
selected: selected || false
});
this.get('items').push(playlistItem);
this.get('shuffledItems').push(playlistItem);
this.set('shuffledItems', _.shuffle(this.get('shuffledItems')));
console.log("this has finished calling");
//Call save to give it an ID from the server before adding to playlist.
songManager.saveSong(song, function (savedSong) {
song.id = savedSong.id;
playlistItem.set('songId', song.id);
console.log("calling save item");
$.ajax({
type: 'POST',
url: 'http://localhost:61975/Playlist/SaveItem',
dataType: 'json',
data: {
id: playlistItem.get('id'),
playlistId: playlistItem.get('playlistId'),
position: playlistItem.get('position'),
songId: playlistItem.get('songId'),
title: playlistItem.get('title'),
videoId: playlistItem.get('videoId')
},
success: function (data) {
playlistItem.set('id', data.id);
},
error: function (error) {
console.error(error);
}
});
});
return playlistItem;
},
addItemByVideoId: function (videoId, callback) {
var self = this;
ytHelper.getVideoInformation(videoId, function (videoInformation) {
var song = songManager.createSong(videoInformation, self.get('id'));
var addedItem = self.addItem(song);
if (callback) {
callback(addedItem);
}
});
},
//Returns the currently selected playlistItem or null if no item was found.
getSelectedItem: function() {
var selectedItem = _.find(this.get('items'), function (item) {
return item.get('selected');
});
return selectedItem;
}
});
return function (config) {
var playlist = new Playlist(config);
playlist.on('change:title', function () {
this.save();
});
return playlist;
};
});
basically I am seeing the property 'items' is populated inside of initialize when I've passed in a config object that does not specify items at all. If I specify a blank items array in my config object, then there are no items in initialize, but this seems counter-intuitive. Am I doing something wrong?
The problem is with using reference types (arrays) in the defaults object. When a new Playlist model is created without specifying an items value, the default is applied. In case of arrays and objects this is problematic, because essentially what happens is:
newModel.items = defaults.items
And so all models initialized this way refer to the same array. To verify this, you can test:
var a = new Playlist();
var b = new Playlist();
var c = new Playlist({items:[]});
//add an item to a
a.get('items').push('over the rainbow');
console.log(b.get('items')); // -> ['over the rainbow'];
console.log(c.get('items')); // -> []
To get around this problem, Backbone supports defining Model.defaults as a function:
var Playlist = Backbone.Model.extend({
defaults: function() {
return {
id: null,
userId: null,
title: 'New Playlist',
selected: false,
position: 0,
shuffledItems: [],
history: [],
items: []
};
}
});