Ionic collection-repeat with ion-radio - angularjs

I'm having a problem with setting checked on selected value using Icon collection-repeat with ion-radio.
Using the collection-repeat, if the selected item is the first item in the list, setting checked wouldn't work. To make it works I found, I need to make a delay assigning list data.
(If using ng-repeat, it works. But the list could be long, so I need to use the collection-repeat)
Example,
Template)
<ion-content class="has-header" ng-controller="Ctrl">
<div class="list">
<ion-radio
collection-repeat="item in list"
ng-model="selectedItem"
ng-value="item.id">
{{ item.n }}
</ion-radio>
</div>
</ion-content>
Controller)
angular.module('starter', ['ionic'])
.run(function($ionicPlatform) {
})
.controller('Ctrl',function($scope, $timeout) {
$scope.selectedItem = 1; // the first item
var list = [];
for (index = 1; index < 3; ++index) {
list.push({id: index, n: 'Item n. ' + index});
}
$scope.list = list;
});
The first item of the list wouldn't be checked. To make it works,
replace
$scope.list = list;
with
$timeout(function() {
$scope.list = list;
}, 500);
I want to know why it happened, and I don't think the 500ms is guaranteed, so I need to know right way to solve this. Please advice me.

It makes complete sense that you want to use collection-repeat over ng-repeat since the list could potentially be very long, and would be unnecessary to render all the items in the DOM at once using ng-repeat. Unfortunately this is a known bug within Ionic from what I have read and the work around to this is quite hacky. For instance the code below works with making active the 2nd radio:
Controller
.controller('Ctrl',function($scope, $timeout) {
$scope.data = {
selectedItem: 2
};
var list = [];
for (index = 1; index < 3; ++index) {
list.push({id: index, n: 'Item n. ' + index});
}
$scope.list = list;
});
HTML
<ion-content class="has-header" ng-controller="Ctrl">
<div class="list">
<ion-radio collection-repeat="item in list" ng-model="data.selectedItem" ng-value="item.id">
{{ item.n }}
</ion-radio>
</div>
</ion-content>
But when you change the selected item to 1, it does not show. Below is a workaround for what you are looking for. Start your loop at 0 and then hide that item using CSS (like I said "hacky"), give it a try.
Controller
.controller('Ctrl',function($scope, $timeout) {
$scope.data = {
selectedItem: 1
};
var list = [];
for (index = 0; index < 5; ++index) {
list.push({id: index, n: 'Item n. ' + index});
}
$scope.list = list;
});
HTML
<ion-content class="has-header" ng-controller="Ctrl">
<div class="list">
<ion-radio
collection-repeat="item in list" ng-model="data.selectedItem" ng-value="item.id" item-height="54" item-width="100.5%">
{{ item.n }}
</ion-radio>
CSS
.item-radio:first-of-type {
display: none;
}
.item-radio {
margin-top: -54px !important;
}
Hope this helps.

Related

IONIC: unable to load dynamic content in `ion-infinite-scroll`

I am new with ionic framework.Currently i am working on ionicsidemenu app.
I have 100 plus records i want to display 20 records at once. When scroll down get next 20 records. For this i am using ion-infinite-scroll but i am unable to understand how to call next 20 records. I am using webservice for fetching records.
Please help me.
You have to use array instead of object in this case because pushing items in array is easier than pushing into object. Ionic documentaton also uses array in their example.
View:
<div ng-repeat="item in data">...</div>
<ion-infinite-scroll (ionInfinite)="getData()">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
Controller:
$scope.data = [];
var page = 1;
$scope.getData = function(){
$http.get('http://example.com?page='+page).then(function(response){
page++;
$.each(response,function(key,item){
$scope.data.push(item);
});
}, function(error){
});
}
When scroll reach to ion-infinite-scroll function will called. at beginning there is no data on screen so without scrolling ion-infinite-scroll function called automatically to load first page.
use limitTo together with Infinite scrolling. AngularJS ng-repeat offers from version 1.1.4 the limitTo option. I slightly adapted the Infinite Scroll directive to make scrolling within a container possible that does not have height 100% of window.
ng-repeat="item in items | orderBy:prop | filter:query | limitTo:limit"
Notice that limit is a variable in the $scope, so changing it automatically adjusts the number of rendered items. And incrementing limit, only renders the added elements.
<table>
<tr ng-repeat="d in data | limitTo:totalDisplayed"><td>{{d}}</td></tr>
</table>
<button class="btn" ng-click="loadMore()">Load more</button>
//the controller
$scope.totalDisplayed = 20;
$scope.loadMore = function () {
$scope.totalDisplayed += 20;
};
$scope.data = data;
or try out this solution
<body>
<pane ng-controller="MainCtrl">
<header-bar title="'Infinite Scroll Example'">
</header-bar>
<content has-header="true" padding="true" on-infinite-scroll="addMoreItem">
<div class=" list padding">
<div ng-repeat="item in items | limitTo:numberOfItemsToDisplay" class="item" type="item-text-wrap">
<h3>{{item}}</h3>
</div>
</div>
</content>
</pane>
</body>
js code
angular.module('myApp', ['ionic'])
.controller('MainCtrl', function($scope) {
$scope.numberOfItemsToDisplay = 20; // number of item to load each time
$scope.items = getData();
function getData() {
var a = [];
for (var i=1; i< 1000; i++) {
a.push(i);
}
return a;
}
$scope.addMoreItem = function(done) {
if ($scope.items.length > $scope.numberOfItemsToDisplay)
$scope.numberOfItemsToDisplay += 20; // load 20 more items
done(); // need to call this when finish loading more data
}
});
while on scrolling will display 20 items.

AngularJS remove NULL from ng-repeat

I'm currently developing an AngularJS web application.
What I'm trying to achieve:
List each item using the ng-repeat method and remove any null values.
Correct - One, Two, Three, Four
Incorrect - One, Two, Three, Four, Null (empty ng-repeat item)
Current Problems:
I've tried several methods todo this, including using the ng-hide function and creating a array filter but I can't seem to get either working correctly.
Any help / advice would be helpful!
Array
[ "One", "Two", "Three", "Four", null ]
HTML:
<md-list>
<md-list-item class="md-3-line" ng-repeat="item in parseQ4P2 track by $index">
<div class="md-list-item-text">
<p>{{item}}</p>
</div>
<md-divider ng-if="!$last"></md-divider>
</md-list-item>
</md-list>
Failed Filter:
dashApp.filter('removeBlackItems', function() {
return function(inputArray) {
var outArray = [];
for (var i = 0; i < inputArray.length; i++) {
if(inputArray[i].length !== 0){
outArray.push(inputArray[i]);
}
}
return outArray;
};
});
You can filter data inside ng-repeat.
Try something like this: http://jsbin.com/sufexe/edit?html,js,output
HTML:
.filter('emptyFilter', function() {
return function(array) {
var filteredArray = [];
angular.forEach(array, function(item) {
if (item) filteredArray.push(item);
});
return filteredArray;
};
}
Controller JS:
.filter('emptyFilter', function() {
return function(array) {
var filteredArray = [];
angular.forEach(array, function(item) {
if (item) filteredArray.push(item);
});
return filteredArray;
};
}
Anwser URL - AngularJS remove empty value
as seen in ng-repeat filter null value not displaying there's no need for a custom filter. Ese angular's existing filter functionality to remove null objects from array in the template/view
<ul ng-repeat="item in items| filter:{item:'!'} track by $index">
<li>{{item.name}}</li>
</ul>

Onclcik ng-show not showing the data in accordion using angularJS and Ionic?

I have tow api one return clinics list and another is onclcik take the clinic id and call the api and display the data to that particular id in accordion list.
But by using ng-show, I am unable to show the data.
Here is my code:
Html code:
<ion-list id = "background">
<div id = "background" >
<ion-item class="item-stable item item-avatar" ng-click = "select(list.ClinicId);" ng-repeat="list in searchlist">
<img ng-src = "img/1.png"/>
<!-- -->
{{list.Name}}
<p> Address: {{list.Address.Address1}}, {{list.Address.Address2}}, {{list.Address.Postcode}}, {{list.Address.State}}, {{list.Address.Suburb}}</p>
</ion-item >
<ion-item class="item-accordion" ng-show="isSelected();" ng-repeat="available in appointments" >
{{available.Appointments.Name}} {{available.Appointments.Speciality}}
</ion-item>
</div>
</ion-list>
JavaScript Code:
$scope.select = function(item) {
api.AvailableAppointments(item)
.success(function(data) {
$scope.availableappointments = data;
console.log(data);
window.sessionStorage['availableappointments'] = angular.toJson(data);
var appointments = window.sessionStorage['availableappointments'];
})
.error(function(data) {
console.log(data);
});
};
$scope.isSelected = function() {
var appointments = window.sessionStorage['availableappointments'];
$scope.appointments = angular.fromJson(accessData);
console.log($scope.appointments);
};
please tell me where I am going wrong....
It would have been great to have a plunker document join to your question but I might an idea why it doesn't work.
Your isSelected() function return nothing that might be why it doesn't change.
Try to add the $index as an argument of your function and compare it to the active clinicID (the one that has been clicked ) then return the answer.
.html
<ion-item class="item-accordion" ng-show="isSelected($index);" ng-repeat="available in appointments" >
{{available.Appointments.Name}} {{available.Appointments.Speciality}}
</ion-item>
.js
$scope.isSelected = function(itemIndex) {
var appointments = window.sessionStorage['availableappointments'];
$scope.appointments = angular.fromJson(accessData);
console.log($scope.appointments);
return (itemIndex == itemSelectionnedIndex);
};
If it doesn't work if ng-show try with ng-if
Edit :
I try to adapt your code on the example that you gave me :
http://codepen.io/anon/pen/wdjAn
You only have to adapt the code to make hide the second accordion when you click a second time.
But it should work...
And your main problems (from what I saw in your code) was that you isSelected returned nothing and your appointments variable is not a list.
Hope it would solve your problem.

AngularJS select image from list

I'm implementing simple pictures list.
here's my code. I have 2 questions:
1. I want to make a single choice whenever the user click an image. Whenever he choose one picture it will clear the other choice. how can I do that?
2. Instead of border I would like to use an icon such as fa-check (http://fontawesome.io/icon/check/). How can I combine it in the css?
Thanks!
css file
.selected {
border:2px solid red;
}
js file
$scope.items = [
{imageUrl: '/app/img/item1.jpg'},
{imageUrl: '/app/img/item2.jpg'}];
$scope.toggle = function (item) {
item.selected = !item.selected;
};
html file
<div class="category rating-type">
<h5>items list</h5>
<div class="pics-continer">
<ul>
<li ng-repeat="item in items" ng-click="toggle(item)" ng-class="{'selected':item.selected}">
<div style="background-image: url({{item.imageUrl}});height:36px; width:40px;display:inline-block"></div>
</li>
</ul>
</div>
Change your taggle method as follows to have a single select image list.
$scope.toggle = function (item) {
$scope.selectedImage = item.imageUrl;
};
And change the view as
<li ng-repeat="item in items" ng-click="toggle(item)" ng-class="{'selected':item.imageUrl == selectedImage}">
<img src="{{item.imageUrl}}" style="height:36px; width:40px;"/>
</li>
So only one image can be selected at the same time.
For using an icon instead of border you can set the icon as background image.
the following link are usefull
CSS background-position Property
I think it is best put as much code as possible in the controller - this is easier to test. So: the html snippet:
<li ng-repeat="item in items" ng-click="selectItem(item)"
ng-class="{'fa fa-check':isSelected(item)}">
<div style="background-image: url({{item.imageUrl}});
height:36px; width:40px;display:inline-block"></div>
</li>
the controller:
controller('TestController', function($scope){
$scope.items = [
{imageUrl: '/app/img/item1.jpg'},
{imageUrl: '/app/img/item2.jpg'}
];
$scope.selectedItem = null;
$scope.selectItem = function(item){
$scope.selectedItem = item;
};
$scope.isSelected = function(item){
if($scope.selectedItem===null){
return false;
}
return item.imageUrl === $scope.selectedItem.imageUrl;
};
})
how to setup fontawesome is documented here: http://fontawesome.io/get-started/ After that you can use the css class names provided by fontawesome. Also included in the example above.
$scope.items = [
{imageUrl: '/app/img/item1.jpg'},
{imageUrl: '/app/img/item2.jpg'}];
$scope.toggle = function (item) {
item.selected = !item.selected;
};
that item is a index for items, but you didn't set selected in your items array . So item.selected it's threw undefined error
Please try this way
$scope.items = [
{imageUrl: '/app/img/item1.jpg',selected:true},
{imageUrl: '/app/img/item2.jpg',selected:false}];

Tracking current selected item with AngularJS

I'm new to AngularJS and can't find any suitable answer for this. My app currently consists of a list of items displayed via Angular. There is also a label which displays the name of the currently selected item, and an input box which allows the name of the currently selected item to be modified.
What I cannot figure out is how to simultaneously:
Allow the selection of an item, which triggers the update of the label and the input box text to display the name of the newly selected item
Allow editing of the name in the input box which triggers the update of the label displaying the currently displayed item name
Edits to the name should be reflected in the original model item
At the moment, i'm trying to keep track of which item is current via a flag against the item and this isn't doing what I want. Ideally I would replace currentItem in the below with a direct reference to the item in items with isCurrent=true.
Current item name label:
`<div id="CurrentItem" data-ng-model="currentItem">{{currentItem.name}}</div>`
Current item name input box:
`<input id="ItemName" type="text" data-ng-model="currentItem" value="{{currentItem.name}}" />`
Display all items:
<div data-ng-repeat="item in items" data-ng-click="changeItem(item)">`
<img src="images/ItemIcon.png">
<div>{{item.name}}</div>
Controller:
var CoreAppController = function($scope, $location) {
$scope.changeItem = function(item) {
var length = $scope.items.length;
while(length-- ) {
$scope.items[length].isCurrent = false;
}
$scope.currentItem = item;
$scope.items.indexOf(item).isCurrent = false;
}
$scope.createItem = function(name, layout) {
$scope.items.push({ id: $scope.items.length + 1,
name: name,
isCurrent: false
});
}
// Initialisation
$scope.items = [];
$scope.createItem("Item 1");
$scope.createItem("Item 2");
$scope.items[0].isCurrent = true;
$scope.currentItem = $scope.items[0];
}
Any advice appreciated!
I'm not sure about your current code, but here is a mock up that does what it appears you're requesting.
The JS
app.controller('MainCtrl', function($scope) {
$scope.items = [
{ name: 'foo' },
{ name: 'bar' },
{ name: 'test' }
];
$scope.editing = null;
$scope.editItem = function(item) {
$scope.editing = item;
}
});
and the markup
<body ng-controller="MainCtrl">
<ul>
<li ng-repeat="item in items">
{{item.name}}
<a ng-click="editItem(item);">edit</a>
</li>
</ul>
<div ng-show="editing">
<input type="text" ng-model="editing.name"/>
<span>{{editing.name}}</span>
</div>
</body>
Hopefully that helps. If you need more of a description, let me know.

Resources