3

I have an array in Knockout view model which looks like so:

this.Activities = ko.observableArray([
{ "date": "28/11/2012 00:00:00",
  "activities": [
     { "company": "BOW",
       "description": "Backup Checks",
       "length": "60"
     },
     { "company": "AMS",
       "description": "Data Request",
       "length": "135"
     },
  ]},
{ "date": "30/11/2012 00:00:00",
  "activities": [
     { "company": "BOW",
       "description": "Backup Checks",
       "length": "60"
     },
     { "company": "SLGT",
       "description": "Software Development",
       "length": "240"
     },
     { "company": "BOW",
       "description": "Data Request",
       "length": "30"
     },
  ]},
]);

I use this code to add a new element to it:

this.Activities.push(new NewActivity(company, description, length, fullDate));

Which uses NewActivity function:

function NewActivity(company, description, length, date) {
    this.date = date;
    this.activities = [{ "company": company, "description": description, "length": length }];
}

And it works fine. However, it creates an entirely new object every time it is getting released. I need to implement a condition when the code would check for the date of the objects already created. If the newly created object had the same date, activity details should be added to activities array within the Activities array for that date.

How can I do it?

All of the data for the Activities array comes from the model in the strongly typed view in MVC application:

this.Activities = ko.observableArray([
        @foreach (ActivitySet aSet in Model)
        {
            @:{ "date": "@aSet.Date",
            @:"activities": [
                 foreach(Activity a in aSet.Activities)
                 {
                     @:{ "company": "@a.Companies.Select(c => c.Title).Single()",
                       @:"description": "@a.Descriptions.Select(c => c.Title).Single()",
                       @:"length": "@a.LengthInMinutes"
                     @:},
                 }
            @:]},
        }
]);

1 Answer 1

4

I suggest that you create a few entities describing your activities:

// Details
function ActivityDetails(company, description, length) {
    this.company = ko.observable(company);
    this.description = ko.observable(description);
    this.length = ko.observable(length);
}

// Activity
function Activity(date, activityDetails) {
    this.date = ko.observable(date);
    this.details = ko.observableArray(activityDetails);
}

The you can control activities in the following manner:

function ViewModel () {
    var self = this;

    this.Activities = ko.observableArray([
        // Activities here
    ]);

    this.addActivity = function (activity) {
        var flag = false;
        ko.utils.arrayMap(self.Activities(), function (item) {
            // Flag is here so it doesn't keep checking further in iterations
            if (!flag) {
                if (item.date() === activity.date()) {
                    item.details.push(activity.details);
                    flag = true;
                }
            }
        });
        // Case where activity date was not found in existing records
        if (!flag) {
            self.Activities.push(activity);
        }
    }
}

This requires your view model to have a custom add method which I have provided an example of. Note that everywhere I am resolving observable values, so if you are using non-observable ones remove the function calls.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks, I'll give it a try. Looks promising
I get the logic behind your answer. Unfortunately AddActivity function doesn't work for me. This line is not executed: ko.utils.arrayMap(self.Activities, function (item) the code just passes it without getting into the function!
@Bartosz Yes it should have been self.Activities() not self.Activities. Corrected the answer.
Yes, I found it up myself, however it still didn't work for me. So I found another solution: ko.utils.arrayForEach(this.Activities(), function(feature) { if(feature.date == activity.date()) { feature.details.push(new ActivityDetails(company, description, length)); flag = true; } }); This time push method doesn't work for me!?%##"^~~# WHYYY
@Bartosz From what I see your date is not observable according to your code. If not you use feature.date, otherwise feature.date(). What exactly doesn't work in the code example I have provided?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.