简体   繁体   中英

Compute value using other items in associative array

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.

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;
 });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM