Create Things tasks in a loop

I have a prompt where I type in a bunch of tasks. I then send these tasks to a structured JSON file as well as to Things as “to dos”. To grab the todos, I loop through the JSON object to grab various bits of information about them. I have everything working fine, except the script bounces back and forth between Drafts and Things for each todo. I am hoping to find a way for the Container to grab all the todos at once and send them one time only. I figure this must mean pulling the Container out of the loop somehow, but I’m not sure how to name the variables or create an array of todos in order to make this happen. Would love any suggestions.

Here’s the code that comes after the prompt. I can post more or the JSON if that’s helpful.

if (p.show())
{
    // Loop through prompt values and update JSON as well as create Things tasks
    for (let goal in json)
    {
        
        let field = goal + "tNames";
        let tasks = p.fieldValues[field];
        json[goal].priority[0].daily.unshift({"date":dStamp,"tasks":[],"enough":false,"description":""});
        if (p.fieldValues[field])
        {
            let task = tasks.split(/\r?\n/);
            for (let i in task)
            {
                json[goal].priority[0].daily[0].tasks.unshift({"name":task[i],"complete":false});
            }
            for (let j in json[goal].priority[0].daily[0].tasks)
            {
                let todo = TJSTodo.create();
                todo.title = json[goal].goal + ": " + json[goal].priority[0].daily[0].tasks[j].name;
                todo.when = rDate;
                todo.heading = json[goal].priority[0].name;
                todo.list = "Goals";
                var container = TJSContainer.create([todo]);
                var cb = CallbackURL.create();
                cb.baseURL = container.url;
                var successT = cb.open();
                if (successT) {
                    console.log("Project created in Things");
                }
                else {
                    context.fail();
                }
            }
         }
        let output = JSON.stringify(json);
        let success = fmCloud.writeString("/Goals/goals-things.json",output);
        }
        
    }
else {
    context.cancel();
}
~~~

Have you looked at the example on the container page in the documentation?

It has two tasks that each get added to the project. Those two could have been added using a loop. if you aren’t adding them under a project, I would imagine you would be adding them as separate items I the array the container is passed. So build your project/array in the loop and push it into the container after the loop.

Does that give you enough to go on?

So, I guess I’m confused about how to iterate the variable in the loop, and then call those multiple variables in the TJSContainer to push to Things.

Here’s the beginning of my loop:

for (let j in json[goal].priority[0].daily[0].tasks)
            {
                let todo = TJSTodo.create();
                todo.title = json[goal].goal + ": " + json[goal].priority[0].daily[0].tasks[j].name;

instead of “todo”, what can I call the variable so that it is unique on each loop? Or am I confused here?

I think you’re either confused, or I’m entirely wrong.

Here’s the sort of way I’d expect it to look.

if (p.show())
{
	// Loop through prompt values and update JSON as well as create Things tasks
	for (let goal in json)
	{

		let field = goal + "tNames";
		let tasks = p.fieldValues[field];
		json[goal].priority[0].daily.unshift(
		{
			"date": dStamp,
			"tasks": [],
			"enough": false,
			"description": ""
		});
		if (p.fieldValues[field])
		{
			let task = tasks.split(/\r?\n/);
			for (let i in task)
			{
				json[goal].priority[0].daily[0].tasks.unshift(
				{
					"name": task[i],
					"complete": false
				});
			}
			
			// Create an array to hold the tasks
			let arrTasks = [];
			
			// Loop over all the tasks to create and add them to this array
			for (let j in json[goal].priority[0].daily[0].tasks)
			{
				// Create the tasks
				let todo = TJSTodo.create();
				todo.title = json[goal].goal + ": " + json[goal].priority[0].daily[0].tasks[j].name;
				todo.when = rDate;
				todo.heading = json[goal].priority[0].name;
				todo.list = "Goals";
				
				//Add the task to the array
				arrTasks.push(todo);
			}
			// Put the array in the container
			let container = TJSContainer.create(arrTasks);
			
			// Create the callback URL for Things based on the container
			let cb = CallbackURL.create();
			cb.baseURL = container.url;

			// Call it
			if (cb.open())
			{
				console.log("Tasks created in Things");
			}
			else
			{
				context.fail();
			}
		}
		
		// Write out the JSON to a file
		fmCloud.writeString("/Goals/goals-things.json", JSON.stringify(json));
	}
}
else
{
	context.cancel();
}

BUT!!!

  1. I can’t test this as I don’t use Things, so I can’t even slightly begin to test if my understanding from the docs is anything like right.
  2. There are variables used in your example that are not set-up in the snippet you shared, so that makes it much harder to debug as it stands; not that you should always post all of the code, but a simplified, workable sub set is often advisable … though as per #1, because I’m not a Things user, it wouldn’t make any difference to me in this case.

Maybe the above will help? Maybe it’ll confuse, so my apologies in advance if it does :face_with_raised_eyebrow:

That did it! I had to declare the arrTasks variable outside of the initial loop, but once I did that, everything worked. Full post-prompt code pasted below.

Thanks so much for all your javascript guidance in recent forums posts. Your help is really invaluable as I don’t quite know enough javascript to form good google queries and your help has given me the language and methods for learning more about what I’m trying to do. I appreciate your generosity on these forums. :raised_hands:

if (p.show())
{
    // Loop through prompt values and update JSON as well as create Things tasks
    var arrTasks = [];
    for (let goal in json)
    {
        
        let field = goal + "tNames";
        let tasks = p.fieldValues[field];
        json[goal].priority[0].daily.unshift({"date":dStamp,"tasks":[],"enough":false,"description":""});
        if (p.fieldValues[field])
        {
            let task = tasks.split(/\r?\n/);
            for (let i in task)
            {
                json[goal].priority[0].daily[0].tasks.unshift({"name":task[i],"complete":false});
            }
            
            for (let j in json[goal].priority[0].daily[0].tasks)
            {
                var todo = TJSTodo.create();
                todo.title = json[goal].goal + ": " + json[goal].priority[0].daily[0].tasks[j].name;
                todo.when = rDate;
                todo.heading = json[goal].priority[0].name;
                todo.list = "Goals";
                
                arrTasks.push(todo);
            }
         }
        let output = JSON.stringify(json);
        let success = fmCloud.writeString("/Goals/goals-things.json",output);
        }
        var container = TJSContainer.create(arrTasks);
                var cb = CallbackURL.create();
                cb.baseURL = container.url;
                var successT = cb.open();
                if (successT) {
                    console.log("Project created in Things");
                }
                else {
                    context.fail();
                }
        
    }
else {
    context.cancel();
}

Glad you got it working :sunglasses: