Permalink
Browse files

supporting ng:options

  • Loading branch information...
1 parent d09c1c5 commit 5b7cc887cf6a44aedd00f1510fd52033ad167337 Tobias Bosch committed Oct 13, 2011
View
@@ -19,6 +19,8 @@ Changelog
- `ngm:enterKey` was removed. Please use a form with `ng:submit` (and `data-ajax=false`) for this.
- `<input type="range">` did produce two sliders. Bug was introduced in 1.0.2.
- `ngm:event` now expects it's value to be a json string.
+- No special support for `ng:repeat` used in `<option>` elements, as angular does not support this.
+ Added support for `ng:options`.
The changes to the `$activePage`, `onActivate` and `ngm:shared-controller` was made to have a more general
solution that is also possible for sencha touch applications. By this, applications can easily switch between
@@ -6,13 +6,20 @@ define([
return function(element, origBinder) {
var scope = this;
var res = origBinder();
+ var oldVal;
if (name) {
- scope.$watch(name, function(value) {
- var data = element.data();
- for (var key in data) {
- var widget = data[key];
- if (widget.refresh) {
- element[key]("refresh");
+ // Note: We cannot use $watch here, as ng:options uses $onEval to change the options,
+ // and that gets executed after the $watch.
+ scope.$onEval(function() {
+ var newVal = scope.$eval(name);
+ if (newVal!==oldVal) {
+ oldVal = newVal;
+ var data = element.data();
+ for (var key in data) {
+ var widget = data[key];
+ if (widget.refresh) {
+ element[key]("refresh");
+ }
}
}
});
@@ -21,22 +21,22 @@ define(['jquery'], function($) {
fn._create = function() {
var res = oldCreate.apply(this, arguments);
var self = this;
- this.element.bind('elementsAdded elementsRemoved', function(event) {
- event.stopPropagation();
- // refresh when the number of options change.
- self.refresh();
- // The default element may have changed, save it into the model
- self.element.trigger('change');
- });
- // Initially fire a change event. Needed when the options are built using
- // ng:repeat.
- self.element.trigger('change');
+
+ // Note: We cannot use the prototype here,
+ // as there is a plugin in jquery mobile that overwrites
+ // the refresh and open functions...
+ var oldRefresh = self.refresh;
+ self.refresh = function() {
+ // The refresh is not enough (for native menus): also
+ // update the internal widget data to adjust to the new number of options.
+ this.selectOptions = this.element.find( "option" );
+ return oldRefresh.apply(this, arguments);
+ };
+ // Refresh the menu on open.
+ var oldOpen = self.open;
+ self.open = function() {
+ this.refresh();
+ return oldOpen.apply(this, arguments);
+ };
};
- var oldRefresh = fn.refresh;
- fn.refresh = function() {
- // The refresh is not enough: also
- // update the internal widget data to adjust to the new number of options.
- this.selectOptions = this.element.find( "option" );
- return oldRefresh.apply(this, arguments);
- }
});
@@ -12,10 +12,8 @@
<script src="lib/jquery-1.6.2.js"></script>
- <script src="lib/angular-0.9.19.js"></script>
- <!--
+ <script src="lib/angular-0.9.19.js" ng:autobind></script>
<script src="lib/jquery.mobile.noinit.js"></script>
- -->
<script src="lib/jquery.mobile-1.0b3-oc1.js"></script>
<script src="lib/require.js" data-main="jqm-angular"></script>
<script>
@@ -27,19 +25,20 @@
<script>
function TestController() {
- this.list = [1,2,3,4,5,6,7,8,9,10,11];
+ this.test = function() {
+ $("start").append('<div></div>');
+ $("start").after('<div></div>');
+ }
}
</script>
<div data-role="page" id="start" ng:controller="TestController">
<div data-role="content">
- <ul data-role="listview">
- <li ng:repeat="l in list.$paged()">{{l}}</li>
- <li ngm:if="list.$paged().hasMorePages()">
- <a href="" ngm:click="list.$paged().loadNextPage()">...</a>
- </li>
- </ul>
+ <select name="test" ng:options="l for l in list" data-native-menu="false"></select>
+
+ <button ng:click="list = [1,2];">Save</button>
+ {{test}}
</div>
</div>
@@ -71,23 +71,6 @@ define(function() {
});
});
- it('should save the default ui value into the model when using ng:repeat in the options', function() {
- loadHtml('/jqmng/ui/test-fixture.html', function(frame) {
- var page = frame.$('#start');
- page.append(
- '<div data-role="content" ng:init="l = [\'v1\',\'v2\']">' +
- '<select name="mysel2" id="mysel2" data-native-menu="true"><option ng:repeat="e in l" value="{{e}}">{{e}}</option></select>' +
- '</div>');
- });
- runs(function() {
- var page = testframe().$("#start");
- var select = page.find("#mysel2");
- expect(select[0].value).toEqual("v1");
- var scope = select.scope();
- expect(scope.$get('mysel2')).toEqual("v1");
- });
- });
-
it('should save the model value into the ui', function() {
loadHtml('/jqmng/ui/test-fixture.html', function(frame) {
var page = frame.$('#start');
@@ -159,74 +142,51 @@ define(function() {
});
});
- it('should refresh the default value when the number of options changes', function() {
- loadHtml('/jqmng/ui/test-fixture.html', function(frame) {
- var page = frame.$('#start');
- // Note: Be sure to use ng:repeat, as this is the most problematic case!
- page.append(
- '<div data-role="content">' +
- '<select ng:repeat="item in [1]" name="mysel" id="mysel" data-native-menu="false"><option value="v1" ngm:if="option1" default="true">v1</option><option value="v2" ngm:if="option2">v2</option></select>' +
- '</div>');
- });
- runs(function() {
- var page = testframe().$("#start");
- var select = page.find("#mysel");
- expect(select.children('option').length).toEqual(0);
- var scope = select.scope();
- scope.option1 = false;
- scope.option2 = true;
- expect(scope.mysel).toBeFalsy();
- scope.$eval();
- expect(scope.mysel).toEqual('v2');
- });
- });
-
it('should refresh when the dialog opens', function() {
loadHtml('/jqmng/ui/test-fixture.html', function(frame) {
var page = frame.$('#start');
// Note: Be sure to use ng:repeat, as this is the most problematic case!
page.append(
'<div data-role="content">' +
- '<select ng:repeat="item in [1]" name="mysel" id="mysel" data-native-menu="false"><option value="v1" ngm:if="option1" default="true">v1</option><option value="v2" ngm:if="option2">v2</option></select>' +
+ '<select ng:repeat="item in [1]" name="mysel" id="mysel" data-native-menu="false" ng:options="o for o in options"></select>' +
'</div>');
});
runs(function() {
var page = testframe().$("#start");
var select = page.find("#mysel");
var scope = select.scope();
- scope.option1 = false;
- scope.option2 = true;
+ scope.options = [1,2];
+ scope.mysel = 1;
scope.$eval();
select.selectmenu('open');
- expect(page.find(".ui-selectmenu li").length).toEqual(1);
+ expect(page.find(".ui-selectmenu li").length).toEqual(2);
});
});
- it('should be able to display the label of a new entry when the options grow', function() {
+ it('should be able to display the label of a new entry when the options grow in a native menu', function() {
loadHtml('/jqmng/ui/test-fixture.html', function(frame) {
var page = frame.$('#start');
// Note: Be sure to use ng:repeat, as this is the most problematic case!
page.append(
'<div data-role="content">' +
- '<select data-native-menu="true" name="myval" id="mysel"><option ng:repeat="e in list" value="{{e.key}}">{{e.value}}</option></select>' +
+ '<select data-native-menu="true" name="myval" id="mysel" ng:options="e.value for e in list"></select>' +
'</div>');
});
runs(function() {
var page = testframe().$("#start");
var select = page.find("#mysel");
var scope = select.scope();
expect(scope.myval).toBeFalsy();
- scope.list = [{key: 'key1', value:'value1'}];
+ scope.list = [{value:'value1'}];
+ scope.myval=scope.list[0];
scope.$root.$eval();
- expect(scope.myval).toBe("key1");
});
waitsForAsync();
runs(function() {
var page = testframe().$("#start");
expect(page.find(".ui-select .ui-btn-text").text()).toEqual("value1");
});
});
-
});
});

0 comments on commit 5b7cc88

Please sign in to comment.