{ "id": "117158", "key": "ALOY-744", "fields": { "issuetype": { "id": "4", "description": "An improvement or enhancement to an existing feature or task.", "name": "Improvement", "subtask": false }, "project": { "id": "11113", "key": "ALOY", "name": "Alloy", "projectCategory": { "id": "10400", "description": "Tools for developing applications", "name": "Tooling" } }, "fixVersions": [ { "id": "15404", "description": "Alloy 2.0.0", "name": "Alloy 2.0.0", "archived": false, "released": false } ], "resolution": null, "resolutiondate": null, "created": "2013-07-14T11:49:18.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [ "alloy", "controller", "scope", "views" ], "versions": [], "issuelinks": [], "assignee": null, "updated": "2018-03-07T22:25:36.000+0000", "status": { "description": "The issue is open and ready for the assignee to start work on it.", "name": "Open", "id": "1", "statusCategory": { "id": 2, "key": "new", "colorName": "blue-gray", "name": "To Do" } }, "components": [ { "id": "12329", "name": "Runtime", "description": "Generic bucket for uncategorized runtime issues" } ], "description": "Right now, compiled Alloy controllers will start with any functions defined in the original controller, then adds the generated view code and finally any inline controller code.\r\n\r\nBecause of this, we are not able to refer to any variables in the Alloy XML views. This could be either view component factories using the {{ns}} attribute or models by using {{{someField}}} in attributes.\r\n\r\nIn [this blog|http://fokkezb.nl/2013/07/14/custom-alloy-view-components/] I show both the need and a workaround for the component factory use-case.\r\n\r\nThere should be a way to specify code that needs to come before the generated view code. Maybe some kind of boundary or and object whose properties will be extracted into the current scope?", "attachment": [], "flagged": false, "summary": "Alloy: Specify controller code that needs to come before generated view code", "creator": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "subtasks": [], "reporter": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "environment": "Any", "comment": { "comments": [ { "id": "261786", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I totally agree with this need, but unfortunately I don't want to do it as a band-aid at the moment. Any additional object or clever use of specific \"exports\" functions would create weird scoping issues and edge cases. The end goal would be to structure Alloy controllers more like true commonjs modules and then have a simple means of converting legacy controllers to the new format. In any case, this is a long discussion for which I am planning to compose a spec document and put forth to the community (google group) in the coming weeks. Sorry for the slightly evasive response, but believe me, this is one of the primary goals of a controller revamp. ", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-15T13:35:49.000+0000", "updated": "2013-07-15T13:35:49.000+0000" }, { "id": "261787", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "Good to know you're on it... looking forward to the doc ;)", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-15T13:39:59.000+0000", "updated": "2013-07-15T13:39:59.000+0000" }, { "id": "262614", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "Looking at what this would be used for, we actually may find a solution in how we already handle binding not yet defined callbacks to UI events by using {{__defers}}.\r\n\r\nOf course this might be more challenging since both the suggested binding of not-yet-defined models and using not-yet-defined {{ns}} are not as easy to postpone as event-binding is. But I just want the idea here for the record ;)\r\n\r\nThe other way around, IF we find a good solutions for changing the order of execution of code, we might have no need anymore for using {{__defers}} for events as well ;)", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-21T18:29:42.000+0000", "updated": "2013-07-21T18:29:42.000+0000" }, { "id": "262616", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "A third solution I was thinking of is analyzing the code to determine what parts of the controller code need to come before the UI.\r\n\r\nI couldn't find an existing Node module that can do this out of the box, but if we can pull it off, it would filter out any variables and functions used in the UI code and move those to the top of the controller.\r\n\r\nThis would solve both event-binding, model-binding, namespaces etc.", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-21T18:34:10.000+0000", "updated": "2013-07-21T18:34:10.000+0000" }, { "id": "262660", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-22T15:29:15.000+0000", "updated": "2013-07-22T15:29:42.000+0000" }, { "id": "262945", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "At the London Titanium meetup, while speaking about this with people I thought about another solution. Since, the Alloy compiler moves all functions to the top, why not use a self-executing function to do any pre-UI stuff. But a quick test showed these type of functions don't get promoted :(\r\n\r\nMaybe we can tweek UglifyJS to actually do promote (hoist) self-executing functions to the top. I think coming from jQuery and other frameworks, didn't would feel like a hack at all:\r\n\r\n{code}\r\n(function($) {\r\n\r\n $.myModel = Alloy.Collections.myCollection.get(arguments[0].modelId);\r\n\r\n})(this);\r\n{code}\r\n\r\n\r\nOf course we could move the {{$ = this;}} statement even before the functions, it can be even more simple.", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-24T06:40:02.000+0000", "updated": "2013-07-24T06:40:17.000+0000" }, { "id": "262965", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Definitely not. [Immediately-invoked function expressions|http://benalman.com/news/2010/11/immediately-invoked-function-expression/] (IIFE) are meant to be invoked exactly where they are placed. Plain declarations can be hoisted since they are considered to be global to the current context anyway. Variables can be hoisted due to the lack of block scope. But moving IIFEs is dangerous and almost certainly would lead to bad, unexpected behavior.", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-24T12:33:12.000+0000", "updated": "2013-07-24T12:33:12.000+0000" }, { "id": "262976", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "Ouch... ;)", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-24T15:29:00.000+0000", "updated": "2013-07-24T15:29:00.000+0000" }, { "id": "326999", "author": { "name": "ppritchard", "key": "ppritchard", "displayName": "Peter Eddy Pritchard", "active": true, "timeZone": "America/Los_Angeles" }, "body": "How about a method that is invoked in BaseController.js? BaseController is required() in before any View XML is executed.\r\n\r\nInvoking a subclass method (like initialize() or beforeRender()) ... to let sub-classes hook into this seems simple and natural.", "updateAuthor": { "name": "ppritchard", "key": "ppritchard", "displayName": "Peter Eddy Pritchard", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2014-10-05T03:58:28.000+0000", "updated": "2014-10-05T03:58:28.000+0000" } ], "maxResults": 9, "total": 9, "startAt": 0 } } }