0

I have been struggling these past few days trying to solve this problem and I'm hoping you all can assist.

I am trying to store a dynamic value in an associative array that is computed using 2 other values from the same array.

Here is the code:

model.TimeLog = {
 StartTime: "2015-01-01T00:00:00",
 EndTime: "2015-01-01T00:00:00",
 TimeDifference: ko.pureComputed(function() {
  var from = StartTime() || "2015-01-01T00:00:00";
  from = new Date(from);
  var to = EndTime() || "2015-01-01T00:00:00";
  to = new Date(to);
  var difference;
  if ((to - from) >= 0)
    difference = to - from;
  else
    difference = 0;
  var timespan = +(difference / 1000 / 60 / 60).toFixed(2);
  return timespan;
 })
}

--------- Section of the HTML page referenced later -------------

<td><input type="text" data-bind="event {onchange: $root.calculateTimeSpan(this,EndTime)}"></input></td>
<td><input type="text" data-bind="event {onchange: $root.calculateTimeSpan(StartTime,this)}"></input></td>

The goal is to have the user pick a start time and end time (using a date/calendar picker) then display the time difference, in hours, to a read only field when either date field is edited.

As to why I am trying to complete the function in this model view as opposed to directly on the page or in a separate script file is because on the page there can be multiple instances of this model and I need the values computed on each instance.

Some other pieces of information that may help:

  • Webpage runs on HTML5, nothing older
  • Knockout JS v3.3.0
  • Designed for latest versions of Chrome and Firefox; no IE

I hope this is enough information for you all. If not, let me know and I will try my best to provide it.

Update

  • Issue is no values are displayed in the read only field. No errors on the back-end and only error in the browser is "ReferenceError: StartTime is not defined"
  • I believe StartTime and EndTime are global variables. I can access them in other files after accessing the model, ie model.StartTime

Things I have tried

  • Instead of running the function on a model, I tried data-binding a function on the html page (using a separate javascript file) (See section above)

NOTE: The html page uses some custom built tags which I cannot post the code of. To access functions in my javascript file I need to use '$root.[function]'. Any values that are within the 'model' are accessible without the use of 'model.[key]'.

Since I am unable to post code samples or screenshots of how the html page renders I'll describe the functionality it has that I am working with:

In the view that I am working on, there is a collection/list of instances of my model. By default no input fields are displayed and there is always a button fixed to the bottom of the page allowing the user to generate a new instance of the model. As the user creates a new instance, that instance of the model is stored in an array, in my case it is called TimeLogGroup. When the user goes to save the page this group, TimeLogGroup, is passed to the back-end to be stored in the database.

So to reiterate the issue, referencing the paragraph above, on each instance of the model there is a start and end time and I need to calculate and display the time-span in a non-editable/read-only field. I have the code to calculate, tested and tried, but am unable to have the value display in the required field.

I hope this further helps you guys.

Cameron
  • 37
  • 10
  • 2
    so what is the problem exactly? any errors you get? please update – Nikos M. May 28 '15 at 21:13
  • http://stackoverflow.com/questions/3224834/get-difference-between-2-dates-in-javascript/15289883#15289883 & http://stackoverflow.com/questions/7763327/how-to-calculate-date-difference-in-javascript – ecarrizo May 28 '15 at 21:13
  • Are `StartTime()` and `EndTime()` actually global functions? – jfriend00 May 28 '15 at 21:15
  • The issue is not in how to calculate the difference between dates. I have the code for that (included). I have tested the calculation code provided in a separate editor and it works to my requirements. Issue is in getting the calculated value to display and update as changes are made to the page. – Cameron May 28 '15 at 21:35
  • You will likely need to add additional code so that someone trying to help you can reproduce the issue. Can you add the html, javascript? – Allen Tellez May 28 '15 at 21:41
  • So, if the error is that `StartTime` is not defined, then guess what - they are NOT globally accessible functions as you assert. Try adding a `console.log(StartTime)` right before you reference it. It will likely show as `undefined`. – jfriend00 May 28 '15 at 21:44
  • There is nothing in my separate javascript file that would pertain to this issue aside from a copy of the function above where I originally tried to data-bind the data. The html on the other hand is a bit more complex and primarily uses custom built html tags that I can't post; at the most I can describe their functions. Also I unfortunatley don't have enough reputation yet to upload a sample image of what the page would look like. – Cameron May 28 '15 at 21:45
  • Wouldn't it matter not if the values are globally accessible since they are trying to be accessed locally (in the same array)? – Cameron May 28 '15 at 21:52
  • Not sure, you mention an associative array but I don't see one. I see a model with a few properties. – Allen Tellez May 28 '15 at 21:52
  • No, in Javascript you can't access a property of an object without an object prefix, no matter where your code is. The `StartTime` function you show is a property of `model.Timelog`, not a global so unless some other code copies those functions to some other scope, you have to access them via that object. – jfriend00 May 28 '15 at 21:55

1 Answers1

0

Your computed will only be updated when observables that it accesses are updated. You need StartTime and EndTime to be observables. You also need to reference them using their qualified names.

Update: oh, and I forgot that the computed will have to be defined outside the object, because it will be evaluated upon creation, and the object members won't exist.

model.TimeLog = {
 StartTime: ko.observable("2015-01-01T00:00:00"),
 EndTime: ko.observable("2015-01-01T00:00:00")
};
model.TimeLog.TimeDifference = ko.pureComputed(function() {
  var from = new Date(model.TimeLog.StartTime());
  var to = new Date(model.TimeLog.EndTime());
  var difference;
  if ((to - from) >= 0)
    difference = to - from;
  else
    difference = 0;
  var timespan = +(difference / 1000 / 60 / 60).toFixed(2);
  return timespan;
 });
Roy J
  • 42,522
  • 10
  • 78
  • 102