Displaying nested JSON data in AngularJS - arrays

I am building a cross platform app using Onsen UI, Monaca and AngularJS.
I have a screen where the user can select from various switches using Onsen UIs built in switches (Switch in List Item). Toggling a switch means that vehicle check needs to be performed, else it is assumed that all checks have passed.
I can display the Check Descriptions (checkitemdesc) as per the JSON below on the list item switches, but when I toggle any of the switches I want to be able to display their related "answers": [{...}] via a modal.
So toggling the "Engine oil level" switch, the user sees a modal with the related checks that can be performed on the "Engine oil level" e.g. Low, top up etc.
JSON example of the data
[{
"fleetcheckitemid": "1",
"checkitemdesc": "Engine oil level",
"answers": [{
"fleetcheckid": "1",
"checkvaluedesc": "Ok"
}, {
"fleetcheckid": "2",
"checkvaluedesc": "Low"
}, {
"fleetcheckid": "3",
"checkvaluedesc": "Top-Up Required"
}]
}, {
"fleetcheckitemid": "2",
"checkitemdesc": "Water level",
"answers": [{
"fleetcheckid": "1",
"checkvaluedesc": "Ok"
}, {
"fleetcheckid": "2",
"checkvaluedesc": "Low"
}, {
"fleetcheckid": "3",
"checkvaluedesc": "Top-Up Required"
}]
}]
My checksController.js used for getting JSON from $http API call which returns a JSON object.
$http.get("http://myfakedomain/api/getfleetchecks.php?fleetid=109").success(function(data)
{
$scope.checkItemDescriptions = data;
});
And my checks.html for displaying switches based on "checkitemdesc" in JSON.
<ul class="list">
<li class="list__item" ng-repeat="checkItemDescription in checkItemDescriptions">
{{checkItemDescription.checkitemdesc}}
<label class="switch switch--list-item">
<input type="checkbox"
class="switch__input"
checked >
<div class="switch__toggle"></div>
</label>
</li>
</ul>
Selecting any of the switches should fire the modal and populate it with the relevant "answers": [{...}] values
modal
<ons-modal var="modal">
<div class="alert-dialog-mask"></div>
<div class="alert-dialog alert-dialog--android">
<div class="alert-dialog-title alert-dialog-title--android">
<div style="text-align: center">Further Details</div>
</div>
<div class="alert-dialog-content alert-dialog-content--android">
<div style="text-align: center; padding-top: 10px; padding-bottom: 15px; padding-left: 10px; padding-right: 10px;">
<p>
Please give further details for<br>
<!-- Display the selected checkitemdesc here - NOT WORKING -->
<strong>{{checkItemDescription[i].checkvaluedesc[i]}}</strong>
</p>
</div>
<!-- Display sub-options for main sections - NOT WORKING-->
<div style="text-align: left; padding-top: 10px; padding-bottom: 15px; padding-left: 10px; padding-right: 10px;">
<!-- Display the selected subitems here - NOT WORKING -->
<label class="checkbox" ng-repeat="checkItemDescription in checkItemDescriptions[i].answers[i].checkvaluedesc">
<input type="checkbox">
<div class="checkbox__checkmark"></div>
<!-- Display the selected subitems here - NOT WORKING -->
{{checkItemDescription[i].answers[i].checkvaluedesc}}
</label>
</div>
</div>
</div>
</ons-modal>
I am able to display the main checks, but how do I do individual checks on each switch and then set the modal values based on that switch?

See this plunker: http://plnkr.co/edit/g952bdedUGuBhC5ez5Im?p=preview
What you do is:
Attach a selected: true/false to the checkitem level as well as the answers level.
Pass the selected row to the modal controller.
Use ng-repeat, using $filter to display the items.
The open modal function:
$scope.openModal = function(items) {
var selectedItems = [];
//get only the selected items
for(var i = 0; i < items.length; i++) {
if(items[i].selected === true) selectedItems.push(items[i]);
}
var modalInstance = $uibModal.open({
templateUrl: 'modalTemplate.html',
controller: MyModalCtrl,
backdrop: 'static',
keyboard: false,
resolve: { //pass selected items to the modal controller
fleetCheckItems: function() {return selectedItems;}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem; //user clicked okay
}, function () {
//user click cancel, figure out something to do with the promise
});
}

Related

How can I create bind a list of elements as a group without ng-repeat?

I've been trying to learn Angular but hit a small blocker. My markup has a list of DIVs which when clicked get toggled (a new class). This is a static list of options and I would like to avoid the ng-repeat directive.
<div ng-app="sampleApp" ng-controller="MainCtrl">
<div class="item" id="germany">Germany</div>
<div class="item" id="poland">Poland</div>
<div class="item" id="sweden">Sweden</div>
<div class="item" id="japan">Japan</div>
<button type="button" ng-click="selected = []">Reset</button>
</div>
I would like to bind it to an array of selections. When clicked, the item's id should be added to the array and when unselected, it should be removed. The existence of the item's id in the selection array defines whether it should have the "active" class.
Below is how I've done it in Angular but this means that I cannot use my static list of DIVs but use the ng-repeat with the JSON. I've toyed around with this and got it correctly bound to the selected array. Clicking the button correctly resets the active class showing that the binding works.
Can I still accomplish this without going down the JSON + ng-repeat way? An example pointing me to this would be nice. Thank you
Here's the CSS:
.item {
border-color: #ddd;
background-color: #fff;
color: #444;
position: relative;
z-index: 2;
display: block;
margin: -1px;
padding: 16px;
border-width: 1px;
border-style: solid;
font-size: 16px;
}
.item.active {
border-color: #ccc;
background-color: #d9d9d9;
}
Here's the JS:
var SampleApp;
(function (SampleApp) {
var app = angular.module('sampleApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.selected = [];
$scope.clicked = function (member) {
var index = $scope.selected.indexOf(member.name);
if (index > -1) {
$scope.selected.splice(index, 1);
member.selected = false;
} else {
$scope.selected.push(member.name);
member.selected = true;
}
console.log($scope.selected);
}
$scope.items = [{
name: "item1"
}, {
name: "item2"
}, {
name: "item3"
}, {
name: "item4"
}, {
name: "item5"
}];
});
})(SampleApp || (SampleApp = {}));
Here's the markup:
<div ng-app="sampleApp" ng-controller="MainCtrl">
<div class="item" ng-repeat="item in items" ng-click="clicked(item)" ng-class="{ active: selected.indexOf(item.name) !== -1 }" id="item.name">{{ item.name }}</div>
<button type="button" ng-click="selected = []">Reset</button>
</div>
<div class="item" id="germany"
ng-click="toggle('germany')"
ng-class="{ active: selected.indexOf('germany') >= 0 }">Germany</div>
and repeat the same pattern for the other countries.
In the controller:
$scope.toggle = function(country) {
var index = $scope.selected.indexOf(country);
if (index >= 0) {
$scope.selected.splice(index, 1);
} else {
$scope.selected.push(country);
}
};
Not sure why you want to avoid ng-repeat though. Using it would avoid repeating the same code again and again in the view, and thus reduce the risk of introducing a bug.

Collection repeat list inside Ionic Pop Up

I have a collection repeat list with a search bar on top of the list (that is inside ionic pop up body). On the real device (Android 4.4), the list displays only 9 records.
I have a codepen created collection repeat inside ionic pop up. Here it displays all the records, but not on the actual device.
Recently I updated from Ionic 1.1.1 to Ionic 1.2.4 . Is it a problem because of the new Ionic version, I also tried Ionic 1.2.4's nightly build it also dint work.
Does the phone's browser version cause a difference, My phone's browser version is "Mozilla/5.0(Linux 4.4.2; en-us; 6043D Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) version/4.0 chrome/ 30.0.0 Mobile Safari/537.36."
Here is the HTML code of the ionic pop up.
<div class="list list-inset" ng-style="{ 'display': 'inline-flex', 'padding': '0'}">
<label class='item item-input' ng-style='{ 'border-right-color': '#FFFFFF'}'>
<i class='icon icon-left ion-ios7-search placeholder-icon''></i>
<input type='text' ng-model='search' placeholder='Search'>
</label>
<a class='button button-icon icon ion-ios7-close-empty placeholder-icon'
ng-style='{ 'color': '#B83E2C' }'
on-touch='clearSearch()''>
</a>
</div>
<div class='listPopUpHeight'>
<ion-scroll direction="y" class="available-scroller" style="height:350px">
<ion-list>
<ion-item
class="dataSourceItem"
collection-repeat="item in dataSource | filter:search"
collection-item-width="100%"
item-height="15%"
on-tap="tapped(item)">
{{item.Text}}
</ion-item>
</ion-list>
</ion-scroll>
</div>
Here is the JS code:
angular.module('ionicApp', ['ionic'])
.controller('PopupCtrl', function($scope, $ionicPopup, $timeout) {
$scope.dataSource = [];
$scope.showList = function(){
var list=[];
for (var i = 0; i < 1000; i++) {
list.push({ 'Id': i, 'Text': 'Text_' + i });
}
$scope.dataSource = list;
var listPopup = $ionicPopup.show({
templateUrl: 'popupTemplate.html',
title: 'List',
scope: $scope,
buttons: [
{ text: 'Cancel' },
]
});
};
});
Is there something I am missing out. Kindly do reply.
Thanks in advance :)
Please check below link. I made a popup with radio button with searchbar for Ionic v1.
https://codepen.io/engabdalb/pen/LYpWbZa
HTML
<a class="item" ng-click="open('aracyakit.html')">
Yakıt
<span style="color:#0097A4" style="color:#0097A4" class="item-note" >
{{arackayit.araba_yakit}}
</span>
</a>
<script id='aracyakit.html' type='text/ng-template'>
<label class="item item-input">
<i class="icon ion-search placeholder-icon"></i>
<input type="text" ng-model="arama" placeholder="Arama">
</label>
<ion-radio name="araba_yakit" id="araba_yakit" ng-repeat="ay in arabayakitlari | filter:arama" class="wrapping-list" ng-model="arackayit.araba_yakit" ng-value="'{{ay.value}}'">{{ay.name}}</ion-radio>
</script>
<a class="item" ng-click="open('aracvites.html')">
Vites
<span style="color:#0097A4" style="color:#0097A4" class="item-note" >
{{arackayit.araba_vites}}
</span>
</a>
<script id='aracvites.html' type='text/ng-template'>
<label class="item item-input">
<i class="icon ion-search placeholder-icon"></i>
<input type="text" ng-model="arama" placeholder="Arama">
</label>
<ion-radio name="araba_vites" id="araba_vites" ng-repeat="av in arabavitesleri | filter:arama" class="wrapping-list" ng-model="arackayit.araba_vites" ng-value="'{{av.value}}'">{{av.name}}</ion-radio>
</script>
CSS
.popup-body {
padding: 10px;
overflow: auto;
width: 100%;
}
.popup-open .popup-backdrop,
.popup-open .popup {
pointer-events: auto;
width: 100%;
}
.popup-head {
padding: 0px 0px;
border-bottom: 1px solid #eee;
text-align: center;
}
JS
$scope.arackayit = [];
$scope.arabavitesleri = [
{ value: "Otomatik", name: "Otomatik" },
{ value: "Manuel", name: "Manuel" }
]
$scope.arabayakitlari = [
{ value: "Dizel", name: "Dizel" },
{ value: "Benzin", name: "Benzin" },
{ value: "Benzin-LPG", name: "Benzin-LPG" }
]
$scope.open = function(clicked) {
$ionicPopup.confirm({
templateUrl: clicked,
scope: $scope,
buttons: [{
text: 'Iptal',
type: 'button-default',
onTap: function(e) {
// Change/ write here current page
$state.go('tab.aracekle');
}
}, {
text: 'Tamam',
type: 'button-positive',
onTap: function(e) {
//open next when OK clicked
switch (clicked) {
case 'aracyakit.html':
$scope.open('aracvites.html');
break;
//Do nothing when OK clicked
case 'aracvites.html':
default:
// code block
}
}
}]
});
}

How to create a simple dashboard angular widget?

I installed malhar-angular-dashboard module for my angular application and I want to create a simple widget that displays some dummy text.
HTML view
<div class="row">
<div class="col-md-12">
<div dashboard="timeDashboardsOptions" class="dashboard-container"></div>
</div>
</div>
JavaScript
$scope.timeDashboardsOptions = {
widgetDefinitions: [ // list required
{
name: 'timeWidget', // option required
template: '<div>hello {{widget.title}}</div>',
settingsModalOptions: {
templateUrl: 'views/dashboards/widget-area/time.html'
}
,
onSettingsClose: function(resultFromModal, widgetModel, dashboardScope) {
// do something to update widgetModel, like the default implementation:
jQuery.extend(true, widget, result);
},
onSettingsDismiss: function(reasonForDismissal, dashboardScope) {
// probably do nothing here, since the user pressed cancel
}
}
],
defaultWidgets: [ // list required
{name:'timeWidget'}
]
};
Widget template
<div>
<h3>Time widget</h3>
</div>
When I run it, I get this kind of result:
ul li {
list-style-type: none;
display: inline;
}
.middle {
color: #fff;
background-color: #f0ad4e;
border-color: #eea236;
}
.last {
background-color: #5bc0de;
border-color: #46b8da;
}
<ul>
<li class='first'>timeWidget - missing ???</li>
<li>
<button class='middle'>Default Widgets</button>
</li>
<li class='last'>
<button class='last'>Clear</button>
</li>
</ul>
and the error
TypeError: _.merge is not a function
at Object.WidgetModel (http://localhost:9000/bower_components/malhar-angular-dashboard/dist/malhar-angular-dashboard.js:848:42)
Remove underscore.js and let loadash.js handle it.

How to load image and text of that image paralelly into a div using angularjs

Actually,I'm able to load 3 images(open,new&save icons) into a div using angularjs.Now,I'm trying to place the related text of those images into the same div just below those 3 images.
Like,"open" text should be written just below "open" image.Simialrly,for the remaining images too.How can I achieve this?
Can anyone please help me out regarding this issue ...
My js code:
angular.module('Sample', []).controller('Home', function($scope) {
$scope.imageSources = [];
$scope.imageSources.push('images/open.png');
$scope.imageSources.push('images/new.jpg');
$scope.imageSources.push('images/save.png');
});
My html code:
<div style="margin-top: 15px;">
<img width=40 height=50 style="margin-left: 12px;"
ng-repeat="imageSource in imageSources track by $index"
ng-src="{{imageSource}}"> </img>
</div>
This will work but is not the right way to do it.
I leave the styling up to you.
View:
<div style="margin-top: 15px;" ng-repeat="imageSource in imageSources">
<img width=40 height=50 style="margin-left: 12px;" ng-src="{{imageSource}}" />
<br>
<span style="margin-left: 12px;">{{getFilenameFromPath(imageSource)}}</span>
</div>
Controller:
$scope.imageSources = [];
$scope.imageSources.push('images/open.png');
$scope.imageSources.push('images/new.jpg');
$scope.imageSources.push('images/save.png');
$scope.getFilenameFromPath = function(filename) {
return filename.split("/")[1].split(".")[0];
}
Here is a jsfiddle.
The right way as it has been mentioned in the contents, is to have a collection of object and each objects should have a name and a src property. In your case you should do:
$scope.imageSources = [];
$scope.imageSources.push({
name:"open",
src: "images/open.png"
});
$scope.imageSources.push({
name:"new",
src: "images/new.png"
});
$scope.imageSources.push({
name:"save",
src: "images/save.png"
});
So you will end up with this collection:
[
{
"name": "open",
"src": "images/open.png"
},
{
"name": "new",
"src": "images/new.png"
},
{
"name": "save",
"src": "images/save.png"
}
]
Here is an jsfiddle.

How to manage certain carousel in <ons-list>

I have almost the same question as in Onsen UI Carousel Swipe list item question. But I need to manage a certain carousel (ccall functions a la setActiveCarouselItemIndex()) in ons-list-item tapped on instead of removing list member.
I wrote the code below:
<ons-page ng-controller="TaskListCtrl">
<ons-toolbar>
<div class="center">Home</div>
</ons-toolbar>
<ons-list>
<ons-list-item modifier="chevron" ng-controller="TaskItemCtrl" ng-repeat="task in tasks">
<ons-row>
<ons-col width="60px">
{{ task.id }}
</ons-col>
<ons-col>
<ons-carousel var="taskCarousel" auto-scroll style="width: 100%; height: 70px" ng-click="nextView()">
<ons-carousel-item>
View #1 {{ task.descr }}
</ons-carousel-item>
<ons-carousel-item>
View #2 {{ task.details }}
</ons-carousel-item>
</ons-carousel>
</ons-col>
</ons-row>
</ons-list-item>
</ons-list>
</ons-page>
The code is:
var app = angular.module('app', ['onsen']);
app.controller('AppController', function($scope) {
});
app.controller('TaskListCtrl', function($scope) {
$scope.tasks = [
{
id: "1",
descr: "Task Description #1",
details: "Details of Task #1"
},
{
id: "2",
descr: "Task Description #2",
details: "Details of Task #1"
},
{
id: "3",
descr: "Task Description #3",
details: "Details of Task #1"
},
{
id: "4",
descr: "Task Description #4",
details: "Details of Task #1"
}
];
});
app.controller('TaskItemCtrl', ['$scope', function($scope) {
$scope.nextView = function() {
var currentIndex = $scope.taskCarousel.getActiveCarouselItemIndex();
$scope.taskCarousel.setActiveCarouselItemIndex((currentIndex + 1) % 2); alert($scope.task.descr + "\n" + $scope.taskCarousel.toString());
};
}]);
A tapping any item in list manages only a carousel at the last ons-list-item.
Thank you in advance...
In your code you are naming every carousel item as var="taskCarousel". The problem is that every new carousel item with ng-repeat is "overwriting" the previous var="taskCarousel", so in the end it can only access to the last one. A possible solution would be to name your items dynamically with, for example, your tasks ids:
<ons-carousel var="{{task.id}}" auto-scroll style="width: 100%; height: 70px" ng-click="nextView(task.id)">
<ons-carousel-item>
View #1 {{ task.descr }}
</ons-carousel-item>
<ons-carousel-item>
View #2 {{ task.details }}
</ons-carousel-item>
</ons-carousel>
Notice that now we also send this id when an item is clicked with ng-click="nextView(task.id)". Therefore, in the controller we will need to use bracket notation instead of dot notation to access the element since the parameter we are sending is just a string:
app.controller('TaskItemCtrl', ['$scope', function($scope) {
$scope.nextView = function(taskID) {
var currentIndex = $scope[taskID].getActiveCarouselItemIndex();
$scope[taskID].setActiveCarouselItemIndex((currentIndex + 1) % 2);
};
}]);
You can try it in Codepen here.
Hope it helps :)

Resources