New with canjs: Simple question on arrays / list in list

Hi guys,

I just got started with CanJS, read through the tutorials but am stuck when trying to get the following HTML.

<div class="trip">
 <div class="location"><h1>Location 1</h1>
  <div class="activities><ul><li>Activity 1</li></li>Acivitiy 2</li></ul></div>
 </div>
 <div class="location"><h1>Location 2</h1>
 ... activities again....
 </div>
... more locations ...
</div> //end trip

The idea is: The user can select a variable number of locations and therein add a variable number of activities. Data should be kept in local stores on the client side.

For the locations this was easy. They are stored in var locationStore = can.fixture.store and adding new locations using the “todo tutorial” works like a charm. For listing the locations I use the following template:

<div class="trip">
   {{#each LocationPromise.value}}
      <div class="location">
         <h1>{{name}}</h1>
         <show-activities location="{{name}}"/>
      </div>
   {{/each}}
</div>

As you can see, I want to call another template (show-activties) to list the selected activities within a location. Problem is: I figured out how to pass the location name / or the location id to the show-activities template but I just don’t understand how to set up a variable set of stores to hold the individual activity lists.

Is there a way to use a two dimensional array or a list within a list to accomplish this? I don’t know how many locations the user will add so I need to be flexible and hard coding a couple stores won’t solve the issue.

I am sure this is quite simple I am just not able to see the solution :slight_smile:

Many thanks for your help,

Thomas

Don’t pass location as a string, pass it as a value like:

<show-activities {activities}="activities"/>

http://canjs.com/doc/can-stache-bindings.html

Thanks Justin,

I am slowly wrapping my head around canjs.

Still I don’t find a way to add an item to an empty list using ($click).

The following shows that the trip.List has no element so nothing to bind the click-event to.

Any idea how I change this such that the click event adds a new item to the empty list?

var trip = can.DefineMap.extend({
   Location: "string",
   
   add: function(newname) {
      this.Locations.push({Location: newname});
   }
});
trip.List = can.DefineList.extend({"#": trip });

var template = can.stache.from("trip-template");
var frag = template({triplist: trip.List});
document.body.appendChild(frag);

<script type="text/stache" id="trip-template">
   {{triplist.length}}
   <a href="javascript://" ($click)="{{add(newname: 'test')}}">Add trip</a><br>
</script>

@nada - a couple things I noticed in your example:

  1. You don’t need to put {{ }} around your click handler
  2. You want to put your add function on your List, not on the Map . The way you have it is trying to push into Locations, which is just a string.

Here is a JSBin that I think is accomplishing what you’re looking for: http://jsbin.com/xalejaruxu/1/edit?html,js,output

Thanks,

this definitely helped. Now I setup a JSBin: http://jsbin.com/sapixutoze/edit?html,js,console,output

The issue which is remaining:
Clicking on extend duration always tells me: ($click) couldn’t find method named @extend

This seems to be an issue because I set up the button in the second #each loop. Doing the same one level up in the Location object works fine.

Ok, got this fixed by defining ActivityStream.List.

Now the next issue comes with retrieving data from the server.

Defining url as follows
var testconnect=can.connect.superMap({
url: “/post/ttt/REST/location.php”
});

and doing:
testconnect.getList({}).then(function(data){console.log(data.id);});

only returns: Promise { : “pending” }

How do I access the promise? At the end I want to push this onto my location.list.

Issue here was that for canjs you need to pass the json data in a separate field which you then can push into a list.

I hope this thread helps anyone new with canjs.

Besides that: Canjs does what I need it to do (for now). Thanks guys for your help