Onsen UI switch automatically change - onsen-ui

I am trying to do something straight forward with Onsen UI -- automatically uncheck some checked switches. So, I have a number of switches and I want to mimic the radio-button behaviour (basically toggling one sets all others to non-checked).
I am using angular and I get this error when i try to do it from code.
Uncaught TypeError: document.getElementsByTagName(...)[0].setChecked
is not a function(…)
Basically I tried
$scope.$on('toggle', function(event, data) {
$scope.selected[data] = event.targetScope.model;
for (i = 0; i < $scope.selected.length; i++) {
if (i != data) {
$scope.selected[i] = !$scope.selected[data];
}
}
});
All my switches are added dynamically using:
> var h = '<ons-list-item><div class="center">' + placeResult.name
> + '</div><div class="right"><ons-switch id="switch' + i
> + '" "ng-model="mySwitch' + i
> + '" ng-click="$emit(\'toggle\',' + i
> + ')"></ons-switch> </div></ons-list-item>';
I don't know if dynamically adding them basically has any issues?
I tried the same code with the preset switches and it works.
Thanks

From what I understand, you are trying to make a number of checkboxes with one master checkbox whose checked status is mimicked by all the other boxes/switches.
If this is the case, in Angular you can easily use ng-checked directive. Here is an example:
<input type="checkbox" ng-model="check-all">Check all<br>
<input type="checkbox" ng-checked="check-all">Option 1<br>
<input type="checkbox" ng-checked="check-all">Option 2<br>
<input type="checkbox" ng-checked="check-all">Option 3

Related

Why isn't my ionic app binding the elements?

http://codepen.io/BltzLcht/pen/grBGBB
<h5>Set timer:</h5></span> <input class="time" type="number" ng-model="countdown" placeholder="In Mississippis" ng-change="selectTimer()"/>
I thought that putting {{countdown}} in would work but it doesn't.
Not sure how to bind the task name with the popup either.
The ionic js file doesn't exist on codepen you need to link it from cdn, for instance:
<script src="https://code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
instead of:
<script src="lib/ionic/js/ionic.bundle.js"></script>
Edit:
The task name problem:
In your html view you use ionic directives which change the scope, so your ng-model input saves to the new scope. The easiest way to do that will be:
$scope.countDown = 0; // number of seconds remaining
$scope.taskData = {}; // <-- add this line to declare object
In html change:
<input class="row-center" type="text" ng-model="taskData.Task" placeholder="Task to be done" />
ng-model Task is inside declared taskData object
and in ionicPopup:
title: 'Your ' + $scope.taskData.Task + ' Is Up!',
Setting task time
You should do something similiar (but add new variable, for instance $scope.taskData.countdownTime which will be used only to set the time, no to countdown)
Change in html:
<input class="time" type="number" ng-model="taskData.countdownTime" placeholder="In Mississippis" ng-change="selectTimer()"/>
Then in JS instead of setting 10 in line:
$scope.countDown = 10;
set the number of seconds provided by user:
$scope.countDown = $scope.taskData.countdownTime;

Angular UI typeahead doesn't populate textbox upon selection

I am using Angular UI typeahead directive. I have a list of people that are in the typeahead dropbox. The list of people is an array of objects with properties like LastName, FirstName, CustomerNumber, etc. (Note, that my domain is completely different, and this is a simplification for clarity). Everything works fine if I have the following typeahead control:
<input type="text" ng-model="vm.selectedCustomer"
typeahead-append-to-body="true"
uib-typeahead="i.LastName for i in vm.lstCustomers | filter:$viewValue" />
However, I want to show more customer information in the typeahead dropbox. Let's say, I have a function in the controller:
vm.getFullName = function(customer) {
return customer.LastName + ", " + customer.FirstName + " - " + customer.CustNumber;
}
and corresponding directive:
<input type="text" ng-model="vm.selectedCustomer"
typeahead-append-to-body="true"
uib-typeahead="vm.getFullName(i) for i in vm.lstCustomers | filter:$viewValue" />
Once the selection is made, the model gets populated correctly; however text box shows undefined, undefined - undefined (curiously, the structure looks like getFullName() was applied to an empty value - with comma and dash).
If I go through every element of lstCustomers and apply getFullName(), everything looks fine again:
var lstCustomersFlat = [];
for (i = 0; i < vm.lstCustomers.length; i++) {
var customer = vm.getFullName(vm.lstCustomers[i]);
lstCustomersFlat.push(customer);
}
But I shouldn't have to do that, should I? Am I missing something, or I stumbled upon a bug?
Please try as shown below.
<input type="text" ng-model="vm.selectedCustomer"
typeahead-append-to-body="true"
uib-typeahead="i as vm.getFullName(i) for i in vm.lstCustomers | filter:$viewValue" />

angular code not working in dynamically generated content

I know I've had this happen before but not in exactly this way and I'm having trouble making the necessary changes.
I have a div that starts out empty and hidden as part of a gallery. When I click an image, it populates the div and shows it. Along with the image/content, there's some navigation elements as well. Thing is, those are also dynamically generated and not working since the angular needs to recompile. Here's the function that populates:
$scope.picturePop = function(picID){
match = $.grep($scope.gallery, function(obj) { return obj.id == picID; });
pic = match[0].image;
title = match[0].title;
desc = match[0].desc;
closediv = "<div id=\"divClose\" class=\"floatRight\" ng-click=\"closeParent();\">Close</div>";
navDiv = "";
if(picID > 1){
prev = picID - 1;
navDiv += "<div id=\"picNav\" ng-click=\"picturePop(" + prev + ")\">Previous</div>";
}
if(picID < $scope.picCount){
next = picID + 1;
navDiv += "<div id=\"picNav\" ng-click=\"picturePop(" + next + ");\">Next</div>";
}
$('#innerPictureDisplay').html(closediv + "<br/><br/><img src=\"images/paintings/" + pic + "\" /><p><b>" + title + "</b><\p><p>" + desc + "</p>"+ navDiv);
$('#outerPictureDisplay').css('display','block');
};
How do I make that code "recompile" so that the "CLOSE" and navigational items work?
UPDATE
So, I changed my approach but I'm clearly still missing something:
my new HTML:
<div id="outerPictureDisplay" ng-show="picID > 0">
<div id="innerPictureDisplay">
<div id="divClose" class="floatRight" ng-click="picID = 0;">Close</div>
<div id="picNav" ng-click="picturePop({{prevID}});" ng-show="picID > 1">Previous</div>
<div id="picNav" ng-click="picturePop({{nextID}});" ng-show="picID < picCount">Next</div>
<img src="images/paintings/{{thisPic.image}}" />
<p>
<b>{{thisPic.title}}</b>
</p>
<p>{{thisPic.desc}}</p>
</div>
</div>
my new function:
$scope.picturePop = function(picID){
match = $.grep($scope.gallery, function(obj) { return obj.id == picID; });
$scope.thisPic = match[0];
$scope.picID = picID;
$scope.nextID = picID + 1;
$scope.prevID = picID - 1;
var $content = $('#innerPictureDisplay');
var scope = $content.scope();
$compile($content.contents())(scope);
};
When I click on a pic, it all loads up fine but when I click on a Previous or Next, it closes since it's registering picID as null. I checked and the numbers are indeed getting printed in the code, but angular doesn't see them on the click. They're coming through as undefined - seemingly the compile issue. I tried implementing it all as a directive, even using the suggested link, but I must've done something off since it didn't help.
You can use the angular service $compile like so:
$compile("<a ng-click='myFunction()'>my html</a>")(scope);
And of course you must inject him wherever you are.
Anyway, for God sake, don't use DOM manipulation this way. You should use a directive and feed the content from a model instead.
UPDATE 1
I sugest use incuna's bindHtmlCompile directive that you can found here.

Typeahead Value in Bootstrap UI

I'm working on an app using AngularJS and Bootstrap UI. I've been fumbling my way through using the Typeahead control in Bootstrap UI.
Here's my Plunker
My challenge is I want the user to have the option of choosing an item, but not required to do so. For instance, right now, if you type Test in the text field and press "Enter", Test will be replaced with Alpha. However, I really want to use Test. The only time I want the text to be replaced is when someone chooses the item from the drop down list. My markup looks like the following:
<input type="text" class="form-control" placeholder="Search..."
ng-model="query"
typeahead="result as result.name for result in getResults($viewValue)"
typeahead-template-url="result.html" />
How do I give the user the option of choosing an item, but allow them to still enter their own text?
The issue is that both Enter and Tab confirm the selection of the currently highlighted item and Typeahead automatically selects an item as soon as you start to type.
If you want, you can click off the control to lose focus or hit Esc to exit out of typeahead, but those might be difficult to communicate to your users.
There's an open request in Bootstrap Ui to not auto select / highlight the first item
One solution is to populate the first item with the contents of the query thus far, so tabbing or entering will only confirm selection of the current query:
JavaScript:
angular.module('plunker', ['ui.bootstrap'])
.filter('concat', function() {
return function(input, viewValue) {
if (input && input.length) {
if (input.indexOf(viewValue) === -1) {
input.unshift(viewValue);
}
return input;
} else {
return [];
}};})
HTML:
<input type="text"
ng-model="selected"
typeahead="state for state in states | filter:$viewValue | limitTo:8 | concat:$viewValue"
class="form-control">
Demo in Plunker
I came across this same situation and found no good answers so I implemented it myself in ui-bootstrap Here is the relevant answer. This is probably not the best route to take, but it does get the job done. It makes the first result in the typeahead to be what you're currently typing, so if you tab or enter off of it, it's selected -- you must arrow-down or select another option to get it.
Here is the modified ui-bootstrap-tpls.js file
I added a mustMouseDownToMatch property/attribute to the directive, like:
<input type="text" ng-model="selected" typeahead="item for item in typeaheadOptions | filter:$viewValue" typeahead-arrow-down-to-match="true">
And the javascript:
var mustArrowDownToMatch = originalScope.$eval(attrs.typeaheadArrowDownToMatch) ? originalScope.$eval(attrs.typeaheadArrowDownToMatch) : false;
I also added this function which will put the current text into the first item of the typeahead list, and make it the selected item:
var setFirstResultToViewValue = function (inputValue) {
scope.matches.splice(0, 0, {
id: 0,
label: inputValue,
model: inputValue
});
}
And that is called in the getMatchesAsync call in the typeahead directive:
var getMatchesAsync = function(inputValue) {
// do stuff
$q.when(parserResult.source(originalScope, locals)).then(function(matches) {
// do stuff
if (matches.length > 0) {
// do stuff
}
if (mustArrowDownToMatch) {
setFirstResultToViewValue(inputValue);
scope.activeIdx = 0;
setTypeaheadPosition();
}
// do stuff
};

ng repeat not updating

Hi I am a newbie to angular js and I am hoping someone can help me out with the following problem.
I have a numeric field called numAdults and I need to show a set of field (such as name, address, telephone etc ) numAdult times to get those information for each of those person.
Here is the jsfiddle for the problem jsfiddle link
Here is also an overview of code of the controller
function bookingController($scope){
$scope.numAdults = 1;
$scope.personLoop = function(){
console.log('personLoop called')
return new Array($scope.numAdults);
//return new Array(2);
}
the html
<label for="book_num_adults">Number of adults:</label>
<input id="book_num_adults" type="text" ng-model="numAdults">
<div class="row" ng-repeat="t in personLoop()" style="border:2px solid red;margin-top:10px">
<h4>Person {{$index+1}}</h4>
<input placeholder="name"><br>
<input placeholder="address"><br>
<input placeholder="telephone"><br>
</div>
Can you also help me with how to transform this as an module ( not just a controller based )
Thank you in advance!
Your Fiddle was riddled with errors...
http://jsfiddle.net/bRgTR/5/
Under Frameworks & Extensions, you need to change the 2nd dropdown from "onLoad" to one of the "No wrap" options
Your controller definition is mangled. It's supposed to be: .controller('name', ['depname', function (depname) { })]); -- you had your closing array misplaced.
You should really use semi-colons.
You don't create an array of 5 items in JavaScript like this: var a = new Array(5), that creates an array that contains a 5. Instead, you should do var a = []; a.length = 5;

Resources