Titanium JIRA Archive
Alloy (ALOY)

[ALOY-362] Allow controller-less views with some controller logic

GitHub Issuen/a
TypeNew Feature
PriorityMedium
StatusClosed
ResolutionFixed
Resolution Date2014-05-21T15:18:42.000+0000
Affected Version/sn/a
Fix Version/sAlloy 1.4.0
ComponentsRuntime
Labelsnotable, qe-testadded
ReporterMatthew Congrove
AssigneeTim Poulsen
Created2012-11-02T18:37:47.000+0000
Updated2014-05-22T21:52:04.000+0000

Description

The ability to create views without a controller is quite nice, but it could be taken a step further. During development of a recent application I built numerous controllers with only 1 or 2 lines of code to set properties of elements in the view. For example:
Alloy.createController("MyView", {
	labelText: "Hello, World!",
	imageUrl: "/images/test.png"
}).getView();
$.MyLabel.text = arguments[0].labelText;
$.MyImage.image = arguments[0].imageUrl;
It would be nice if we could pass in parameters to the controller-less view which automatically sets these properties. For example:
Alloy.createController("MyView", {
	MyLabel: {
		text: "Hello, World!"
	},
	MyImage: {
		image: "/images/test.png"
	}
}).getView();
This lets us omit the controller completely.

Comments

  1. Tony Lukasavage 2012-11-02

    I like this idea, with a small change to implementation likely. For the sake of keeping the current convention unchanged, I would prefer to use a spceific reserved property where these "by id" property assignments would happen. Something like:
       Alloy.createController("MyView", {
           views: {
               MyLabel: {
                   text: "Hello, World!"
               },
               MyImage: {
                   image: "/images/test.png"
               }
           }
       }).getView();
       
    or perhaps like this:
       Alloy.createController("MyView", {
           '#MyLabel': {
               text: "Hello, World!"
           },
           '#MyImage': {
               image: "/images/test.png"
           }
       }).getView();
       
    just looking to avoid conflicts with how people currently use it
  2. Matthew Congrove 2012-11-02

    Yes, that makes much more sense. I really like the latter as it keeps everything similar across the filetypes (JS -> TSS).
  3. Tim Poulsen 2014-04-07

    PR: https://github.com/appcelerator/alloy/pull/358 Functional test: Run the app included in the PR. The result should be a white window with two labels: the first with a large gradient background and other properties as set in the index.js controller. Note that the childview.xml contains no properties other than ID. Styles from childview.tss are merged in. There is no childview.js controller file. Properties and values are set in the index.js controller using the new autoView argument.
  4. Tim Poulsen 2014-04-28

    reopened for alternative implementation
  5. Tim Poulsen 2014-04-28

    New PR: https://github.com/appcelerator/alloy/pull/376 Functional test as before. In the new implementation, you no longer use the "autoView" object in your createController() call. Instead, pass an argument object whose keys correspond to the IDs of the components in the child view to which the styles will be applied.
       $.index.add(Alloy.createController('childview', {
       	"#label": {
       		text: 'I am a label',
       		top: 50
       	},
       	"#anotherlabel": {
       		text: 'I am also a label',
       		foo: 'bar' /* a custom/non-existent property */
       	},
       	"#someNonExistentId": { text: 'I do not exist'}
       }).getView());
       
  6. Tim Poulsen 2014-04-28

    For performance reasons, I'm leaning towards the implementation of https://github.com/appcelerator/alloy/pull/377
       $.index.add(Alloy.createController('childview', {
          alloyAutoView: {
             "#label": {
                text: 'I am a label',
                top: 50
             },
             "#anotherlabel": {
                text: 'I am also a label',
                foo: 'bar'
             },
             "#someNonExistentId": { text: 'I do not exist'}
          }
       }).getView());
       
  7. Tim Poulsen 2014-04-29

    OK, I went with a new dedicated method for controller-less views. This offers the best performance for existing apps and "standard" functionality while making controllerless views available to developers via a specific method. See https://github.com/appcelerator/alloy/pull/376 (merged).
       // new method, for instantiating controllerless views
       $.index.add(Alloy.createControllerlessView('childview', {
          "#label": {
             text: 'I am a label',
             top: 50
          }
       }).getView());
       
       // old method for instantiating controllers is still there
       $.index.add(Alloy.createController('normalchild', {
       	text: 'Set the old-fashioned way in the normalchild.js file'
       }).getView());
       
    Final functional test: Run the ALOY-362 test app. The result should be a white window with three labels: the top two are created with the controllerless view technique. The first label has a large gradient background and other properties as set in the index.js controller. Note that the childview.xml contains no properties other than ID. Styles from childview.tss are merged in. There is no childview.js controller file. Properties and values are set in the index.js controller using the new autoView argument. A third label, at the bottom of the screen is created with the traditional createController() method.
  8. Tim Poulsen 2014-04-29

    PR merged
  9. Tony Lukasavage 2014-05-16

    re-open for potential api change
  10. Tim Poulsen 2014-05-20

    The new API moves this functionality to be a method of the controller, which must be invoked after the controller is instantiated. Like this:
        var someView = Alloy.createController('someView');
        someView.updateViews({
           "#myLabel": {
              text: 'I am a label',
              top: 50
           }
        });
        $.index.add(someView.getView());
        
    Note that updateViews() will not apply attributes to or elements within your new controller.
  11. Tim Poulsen 2014-05-20

    New PR https://github.com/appcelerator/alloy/pull/404 Merged to 1_4_X branch and cherry-picked to master
  12. Tim Poulsen 2014-05-21

    Problem on Android was due to case -- sample app used normalChild when the file was named normalchild. The sample app would have failed on an iOS device. I've corrected that. I also made a change that removes an inadvertent SDK dependency (as written, the solution would have required SDK 3.2.0+).
  13. Tim Poulsen 2014-05-21

    New PR https://github.com/appcelerator/alloy/pull/408 has been merged to 1_4_X and master
  14. Federico Casali 2014-05-22

    Verified fixed and working as expected on Android (Google Nexus Galaxy), iOS (iPhone 5) and MobileWeb TiSDK 3.3.0.v20140522110830 Alloy 1.4.0-alpha4 Appcelerator Studio 3.3.0.201405211748 CLI 3.3.0-alpha5 Closing.

JSON Source