{ "id": "117161", "key": "ALOY-743", "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": "15402", "description": "Alloy 1.2.0, concurrent with SDK 3.1.0", "name": "Alloy 1.2.0", "archived": false, "released": true, "releaseDate": "2013-08-15" }, { "id": "15571", "description": "2013 Sprint 15", "name": "2013 Sprint 15", "archived": true, "released": true, "releaseDate": "2013-07-29" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2013-07-18T17:39:44.000+0000", "created": "2013-07-14T17:24:07.000+0000", "priority": { "name": "Medium", "id": "3" }, "labels": [ "alloy", "compile", "namespace", "qe-testadded" ], "versions": [], "issuelinks": [], "assignee": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2013-07-22T23:21:39.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "12329", "name": "Runtime", "description": "Generic bucket for uncategorized runtime issues" }, { "id": "12326", "name": "XML", "description": "View XML and parsing" } ], "description": "The Alloy {{ns}} attribute can be used in a creative manner to load a CommonJS or native module to call the {{createTagName}} method upon, since:\r\n\r\n{code}\r\n\r\n{code}\r\n\r\nWill compile to:\r\n\r\n{code}\r\n$.__views.myId = require('my.module').createMyComponent({ .. });\r\n{code}\r\n\r\nThis works fine, but still feels hacky. I would propose to make a change to {{/Alloy/commands/compile/parsers/default.js}} so that whenever a namespace is given like this:\r\n\r\n{code}\r\n\r\n{code}\r\n\r\nThe generated code would be:\r\n\r\n{code}\r\nif (typeof my.module === 'undefined') var myModule = require('my.module');\r\n$.__views.myId = myModule.createMyComponent({ .. });\r\n{code}\r\n", "attachment": [ { "id": "40918", "filename": "Screen Shot 2013-07-18 at 1.09.50 PM.png", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-19T13:28:53.000+0000", "size": 16558, "mimeType": "image/png" } ], "flagged": false, "summary": "Alloy: Add proper dynamic loading of namespace objects", "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": "261731", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "Here is the PR: https://github.com/appcelerator/alloy/pull/178", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-14T18:11:49.000+0000", "updated": "2013-07-14T18:11:49.000+0000" }, { "id": "261780", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I'm not sure I want to do that right away. For one thing, how could you possibly make a distinction between a globally accessible namespace for creating components and a require()'ed module like you are accounting for? For example, what if this existed in the \"app/alloy.js\"?\n\n{code:javascript}\nvar my = {\n module: {\n createView: function() {\n /* ... */\n }\n }\n}\n{code}\n\nI mention this condition because I've heard of people wanting to wrap Titanium functions and namespaces in their own calls and still leverage them through XML. I get that it feels \"hacky\", but there may need to be a more explicit way to do it. Perhaps bringing the \"module\" attribute over from the tag in Alloy 1.2.0? Not sure yet, need to think about this one. ", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-15T13:10:53.000+0000", "updated": "2013-07-15T13:10:53.000+0000" }, { "id": "261781", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "I thought global scope access from CommonJS modules was deprecated?\r\n\r\nDon't really get your example. The only way to get an object in the controller scope is by requiring a CommonJS module right?", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-15T13:16:02.000+0000", "updated": "2013-07-15T13:16:02.000+0000" }, { "id": "261782", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "BTW, first line of last code snippet needs to be:\r\n\r\n{code}\r\nif (typeof myModule === 'undefined') var myModule = require('my.module');\r\n{code}\r\n\r\nIn the PR I also added support for doing {{require('dir/my.module')}}.", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-15T13:17:48.000+0000", "updated": "2013-07-15T13:17:48.000+0000" }, { "id": "261800", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "No, its not deprecated. In fact, it's now supported on all platforms. That's why you can access the {{Alloy}} namespace in your lib commonjs modules without explicitly requiring it. In any case, I don't like the idea of strings behaving differently based on whether or not we've defined special handling under the hood. It's not terribly intuitive. \n\nIf feel like this would be much more intuitive:\n\n{code:xml}\n\n{code}", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-15T14:28:03.000+0000", "updated": "2013-07-15T14:28:03.000+0000" }, { "id": "261851", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "Well I guess if you can access the global scope, all this is at most a nice 'service', but not required. One could just add this in {{alloy.js}} and then use {{ns=\"myNamespace\"}} wherever they want?\r\n\r\n{code}\r\nvar myNamespace = require('namespace');\r\n{code}\r\n\r\nBut of course this pollutes the global scope (that's why I thought access to global vars was deprecated anyway).", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-15T19:14:34.000+0000", "updated": "2013-07-15T19:15:44.000+0000" }, { "id": "261974", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-16T06:09:08.000+0000", "updated": "2013-07-16T06:09:08.000+0000" }, { "id": "262235", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "You could do it without polluting the global scope though via Alloy.Globals, but that's not ideal either. But back to the core issue here...\n\nI don't like the idea of generating more code where the generated JS is basically guessing whether or not you are using a module. I'd prefer a clear, explicit syntax. And for the , or element one already exists. Take a look at how a native module is included:\n\nhttps://github.com/appcelerator/alloy/blob/master/test/apps/advanced/native_modules/views/index.xml\n\nIt's a specialized . I'm betting with very little effort \"module\" and \"method\" can be ported to arbitrary view XML elements to give the same functionality you are looking for while still be roughly along the lines of this issue and ALOY-747. The expectation would still be that the resulting UI object implements add()/remove(), but the create function could be modified as it is already for native modules. Thoughts?", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-17T21:31:49.000+0000", "updated": "2013-07-17T21:31:49.000+0000" }, { "id": "262298", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "I think you're right and {{Module}} can do the job. I just want to ask for a small change that doesn't alter any of the current behavior of the test.\r\n\r\nI think this PR speaks for it self:\r\nhttps://github.com/appcelerator/alloy/pull/186\r\n\r\nIt fixes the {{Alloy.Module.js}} parser currently not being used at all and as a result of fixing this and just a small change in the {{default.js}} parser now:\r\n\r\n{code}\r\n\r\n\r\n\r\n{code}\r\n\r\nJust another small note. Why do we even need the {{}} tag? I think we can live with just the {{module}} and {{method}} attributes, since already:\r\n\r\n{code}\r\n\r\n\r\n\r\n{code}", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-07-18T07:15:47.000+0000", "updated": "2013-07-18T07:15:47.000+0000" }, { "id": "262338", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "[~fokke] there's a couple reasons for \n\n# It's expressive. It's very clear ata glance that a developer is referencing a native/commonjs module.\n# It changes the node name to \"View\". In the underlying native module system, the default function for creating an instance of a module is \"createView\". If you leave your instance creation as the default, then you don't need to specify a \"method\" attribute in the tag.\n\nSo it's just shorthand for common use cases. And as you stated, after all this dialog, this is probably doable already using the \"module\" and \"method\" functions. In fact, I'm going to put an example in the 1.2.0 repo that shows exactly how to do this. Will update when it's done.", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-18T14:42:11.000+0000", "updated": "2013-07-18T14:42:11.000+0000" }, { "id": "262340", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "No code has been changed in Alloy as a result of this ticket, but I am able to (cleanly) add arbitrary UI components from commonjs modules via XML. These modules can make full use of TSS, inline styles, and XML eventing. To make it very clear how one should do this, I've added the following example app to the repo:\n\nPR: https://github.com/appcelerator/alloy/pull/187\nexample: https://github.com/appcelerator/alloy/tree/master/test/apps/advanced/commonjs_xml\n\nI think that answers pretty much all concerns we had to this point. Now for the sake of keeping the whole conversation tied together, I'm going to take a look at your latest PR [~fokke] and see what contained in it still needs to be addressed, if anything.\n\nPR: https://github.com/appcelerator/alloy/pull/186", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-18T15:48:20.000+0000", "updated": "2013-07-18T15:48:20.000+0000" }, { "id": "262346", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Note: this PR and test is the result of discussion and aggregation of the aforementioned PRs.\r\n\r\nPR: https://github.com/appcelerator/alloy/pull/188\r\nexample app: https://github.com/appcelerator/alloy/tree/master/test/apps/advanced/commonjs_xml\r\n\r\nFunctional testing should be confirmed on all supported platforms with the following steps:\r\n\r\n# Run the example app\r\n# Assert that all views presented in the XML are present in the app. It should look roughly like the attached screenshot\r\n# Click the views with the \"click me\" labels and ensure that they open an alert dialog", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-18T17:39:44.000+0000", "updated": "2013-07-18T17:39:44.000+0000" }, { "id": "262746", "author": { "name": "fcasali", "key": "fcasali", "displayName": "Federico Casali", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Verified as working as expected.\n\nEnvironment:\n\nTitanium SDK 3.1.2.v20130718094558\nAppcelerator Studio 3.1.2.201307191853\nAlloy 1.2.0\nLiveView 0.1.28 (from Beta stream)\n\nAndroid device 4.2.2 - iPhone 5 6.1.4\n\nClosing.", "updateAuthor": { "name": "fcasali", "key": "fcasali", "displayName": "Federico Casali", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-22T23:20:27.000+0000", "updated": "2013-07-22T23:20:27.000+0000" } ], "maxResults": 13, "total": 13, "startAt": 0 } } }