ionic/AngularJs transfer data between views - angularjs

I'm trying to transfer data between two views. I followed the example on http://learn.ionicframework.com/formulas/sharing-data-between-views/ but can't seem to get it right.
essentially my app.js is:
.state('friends', {
url: '/friends',
templateUrl: 'templates/friends.html',
controller: 'FriendsCtrl'
})
.state('friend-detail', {
url: '/friends/:friendId',
templateUrl: 'templates/friend-detail.html',
controller: 'FriendDetailCtrl'
});
In friends.html I have a list of my friends and I am trying to pass the id to friend-detail.html. Here is the content of friends.html:
<ion-content>
<ion-list>
<ion-item class="item-avatar" ng-repeat="friend in friends" ng-href='#/friends/{{friend.id}}'>
<img ng-src="{{friend.face}}">
<h2>{{friend.name}}</h2>
</ion-item>
</ion-list>
</ion-content>
and I am looking for friend.id or friend.name in friend-detail.html. I am able to use {{friend.id}} in friends.html to test and it's working but can't get to new page.
Here is my list just incase:
.factory('Friends', function() {
// Might use a resource here that returns a JSON array
// Some fake testing data
// Some fake testing data
var friends = [{
id: 0,
name: 'Ben Sparrow',
notes: 'Enjoys drawing things',
face: 'https://pbs.twimg.com/profile_images/514549811765211136/9SgAuHeY.png'
}, {
id: 1,
name: 'Max Lynx',
notes: 'Odd obsession with everything',
face: 'https://avatars3.githubusercontent.com/u/11214?v=3&s=460'
}, {
id: 2,
name: 'Andrew Jostlen',
notes: 'Wears a sweet leather Jacket. I\'m a bit jealous',
face: 'https://pbs.twimg.com/profile_images/491274378181488640/Tti0fFVJ.jpeg'
}, {
id: 3,
name: 'Adam Bradleyson',
notes: 'I think he needs to buy a boat',
face: 'https://pbs.twimg.com/profile_images/479090794058379264/84TKj_qa.jpeg'
}, {
id: 4,
name: 'Perry Governor',
notes: 'Just the nicest guy',
face: 'https://pbs.twimg.com/profile_images/491995398135767040/ie2Z_V6e.jpeg'
}];
return {
all: function() {
return friends;
},
get: function(friendId) {
// Simple index lookup
return friends[friendId];
}
}
})
and here are the controllers:
FriendsCtrl:
.controller('FriendsCtrl', function($scope, $state, Friends) {
$scope.friends = Friends.all();
});
NewTransfersCtrl:
.controller('NewTransfersCtrl', function($scope, $stateParams, Friends) {
$scope.friend = Friends.get($stateParams.friendId);
})

See sample here : http://codepen.io/aaronksaunders/pen/gbWgQe?editors=101
basically you should be checking for the stateParams.id to get the id being passed on the URL. It would be easier to show you what is missing if you provided more code.

Related

UI Router, Passing Data From Parent Controller

I'm attempting to refactor a website into Angular through UI-Router. On the parent component I have defined some data on the controller. How do I pass this data to the child nested routed component through UI-Router? UI-Router's resolve only works when you have a binding on data, but I don't know if it's possible to bind the parent controller data to the parent component.
const main = angular.module('main', ['ui.router']);
main.config(function($stateProvider) {
const states = [
{ name: 'parent', url: '/parent', component: 'parent' },
{ name: 'parent.child', url: '/{childUrl}', component: 'child',
resolve: {
data: function($transition$) {
// I want to pass in { name: 'Name1', content: 'Page-Long Content1' }, { name: 'Name2', content: Page-Long Content2' }
// How do I do this?
}
}
}
];
states.forEach(function(state) {
$stateProvider.state(state);
});
});
angular.module('main')
.component('parent', {
template:
'<div ng-repeat="data in $ctrl.data">' +
'<p>{{data.name}}</p>' +
'<a ui-sref="parent.child({ childUrl: data.name })" ui-sref-active="active">Child link</a>' +
'</div>' +
'<ui-view></ui-view>',
controller: function() {
this.data = [
{name: 'Name1', content: 'Page-Long Content1'},
{name: 'Name2', content: 'Page-Long Content2'}
]
}
});
angular.module('main')
.component('child', {
bindings: { data: '<' },
templateUrl: 'link.html',
});
Basically you have an unique identifier of your record in the URL. So by that you can retrieve your data once again from the dataset. For achieving the same, I'd suggest you to put your data in service and then fetch the same data in resolve of your state. Afterward apply an filter over the data and get desired record from it based on childUrl parameter of state.
angular.module('main')
.service('dataService', function(){
var dataService = this;
dataService.getData = getData;
var data = [
{name: 'Name1', content: 'Page-Long Content1'},
{name: 'Name2', content: 'Page-Long Content2'}
];
function getData(){
return data;
}
});
state
const states = [
{ name: 'parent', url: '/parent', component: 'parent' },
{ name: 'parent.child', url: '/{childUrl}', component: 'child',
resolve: {
data: function($transition$, dataService) {
let childUrl = $transition$.params('childUrl');
//in case of API call below will be changed to promise driven code.
return dataService.getData().filter((item) => item.name === childUrl)[0];
}
}
}
];
And inside a parent controller you can fetch data from service directly.
controller: function(dataService) {
this.data = dataService.getData();
}

How to update in ionic

Im trying to update my already existing entries using angularjs and ionic.I have two views, in the first view I have listed the car name and its model name. When the car name is selected, it is directed to second view where the information regarding the selected car name and its models are listed so that they are edited and updated.I have declared $rootScope.selectItem=key; which help to show what is the selected car name. I face problem in update so, I need help in updating the information by replacing the new information with old information.
view 1:
<ion-list>
<ion-item ng-model="carBrand" ng-repeat="name in carSelect">
<button ng-click="selectItem(name)">{{name.name}}</button>
<div class="item" ng-repeat="type in name.types">{{type}}</div>
</ion-item>
</ion-list>
view 2:
<input type="text" ng-model="newName"><br> Select Type:{{selectItem}}</div>
<ion-checkbox ng-repeat="field in fields" ng-model="field.checked" ng-checked="field.checked">
{{field.name}}
</ion-checkbox>
<button ng-click="remove()">Delete</button>
<button ng-click="Update()">Update</button></div>
Controller:
carService.controller('carBrand', ['$scope', 'carRepository', '$rootScope', '$state', '$stateParams', function ($scope, carRepository, $rootScope, $state, $stateParams) {
$rootScope.carSelect = carRepository.data;
$scope.newCarList = [];
$scope.selectItem = function (key) {
$rootScope.selectItem=key;
$state.go('app.carModel');
}
carService.controller('carAdd', ['$scope', '$rootScope', '$state', function ($scope, $rootScope, $state) {
$scope.newName = "";
$scope.fields = [{ id: 1, name: 'Regular' },
{ id: 2, name: 'SUV' },
{ id: 3, name: 'Oversize' },
{ id: 4, name: 'Truck' },
{ id: 5, name: 'Motorcycle' }];
$scope.sample = [];
$scope.Update = function () {
var carType = [];
....}
If I were you, I would change some things to make it more application-like.
First of all, change your state routing:
$stateProvider.state("app.carModel", {
// ..
url: "edit/:id"
}
Then in your selectedItem function:
$scope.selectItem = function (car) {
// assuming your cars have an id property
// you can ofcourse also use something else
$state.go('app.carModel', { id: car.id });
}
Then in your edit/add controller:
carService.controller('carAdd', ['$scope', '$stateParams', 'carRepository', function ($scope, $stateParams, carRepository) {
var carId = $stateParams.id;
// make a copy, so it only gets changed in the repository when the user
// presses 'Update'
$scope.car = angular.copy(carRepository.get(carId));
$scope.fields = [{ id: 1, name: 'Regular' },
{ id: 2, name: 'SUV' },
{ id: 3, name: 'Oversize' },
{ id: 4, name: 'Truck' },
{ id: 5, name: 'Motorcycle' }
];
$scope.sample = [];
$scope.Update = function () {
// ..
// in the save function replace the existing with the edited
carRepository.save($scope.car);
}
}

Repeating multidimensional array object in angular

I have an array that looks like this:
[Object{ 82893u82378237832={ id=8, no=1, type="event", name="Sample1"}}, Object{ 128129wq378237832={ id=9, no=1, type="event", name="Sample2"}} ]
Now ignoring the first part which is just a random token i want to get the array inside that. i.e. id,no,type,name and display them in an ng-repeat, how can i achieve this?
This is how i create the above array:
var obj = {};
obj[data.responseData] = {
id: 8,
no: 1,
type: 'event',
name: ''
}
$scope.items.push(obj);
Your example doesn't include an array.
Anyway here's a good example.
Use map to transform an array to another array and use ng-repeat in a similar way that I've done.
Html:
<div ng-app="app">
<div ng-controller="ctrl">
<div ng-repeat="item in myArr">
{{item}}
</div>
</div>
</div>
JS:
angular.module('app', []).
controller('ctrl', function ($scope) {
var arr = [{
myId: '82893u82378237832',
id: 8,
no: 1,
type: "event",
name: "Sample1"
}, {
myId: '128129wq378237832',
id: 9,
no: 1,
type: "event",
name: "Sample2"
}];
// mapped the new object without myId
$scope.myArr = arr.map(function (item) {
return {
id: item.id,
no: item.no,
type: item.type,
name: item.name
}
});
});
JSFIDDLE.

Updating ng-include from directive in Angular

I am trying to click on a list item that is created via a repeater and update the template value that is being used by ng-inlude. The initial value that is being set in the controller is working fine (shows up in DOM), however when i change the value in the directive, it is not updating the DOM (stays as initial included DOM). When i use fire bug on the directive it looks as though the scope has changed, although I'm not sure if I am missing something, or if i should be doing this some other way.
This is my partial
<div ng-controller="menuCtrl" >
<ul class="sub-menu">
<li ng-repeat="item in menuItems.left" menu-repeater-directive>
<span>{{item.name}}</span>
<a class="reset-menu-btn">×</a>
</li>
</ul>
<div id="lft-wrapper" class="a-wrapper">
<div ng-include="template.url" id="lft-scroller" class="a-scroller"></div>
</div>
</div>
This is my Menu Control
angular
.module('simApp')
.controller("menuCtrl", function($scope, $element) {
$scope.menuItems = {
left: [
{
name: "Table of Context",
url: "static/partials/tree.html"
},
{
name: "Index",
url: "static/partials/dictionary.html"
},
{
name: "Exercises",
url: "static/partials/exercises.html"
},
{
name: "Search Results",
url: "static/partials/results.html"
}
],
right: [
{
name: "About Writer's Help",
url: "static/partials/about.html"
},
{
name: "Tags & Tools",
url: "static/partials/tools.html"
},
{
name: "Your Class",
url: "static/partials/class.html"
},
{
name: "Top Ten",
url: "static/partials/top10.html"
}
]
}
$scope.template = $scope.menuItems.left[0];
});
This is my directive
angular
.module('simApp')
.directive("menuRepeaterDirective", function() {
return function(scope, element, attrs){
var self = this;
this.scope = scope;
this.element = element;
var $ele = $(element);
$ele.find("span").fastClick(function(ev){
//angular specific
var index = $(ev.currentTarget).parent().index();
self.scope.template = self.scope.menuItems.left[index];
//end angular specific
....some other Jquery stuff
});
}
});
Try:
self.scope.$apply(function(){ //Use $apply to let angular aware of the changes.
var index = $(ev.currentTarget).parent().index();
self.scope.$parent.template = self.scope.menuItems.left[index]; //accessing self.scope.$parent instead of self.scope
});
DEMO
Explanation why we have to access self.scope.$parent:
self.scope is the scope of the current item generated by ng-repeat while your ng-include is binding to menuCtrl's scope. self.scope.$parent is menuCtrl's scope in this case.

Inconsistent behavior in AngularJS views populated with Jaydata

I am attempting to build a proof of concept application using AngularJS and Jaydata. I am loosely following the MVC pattern on the AngularJS home page (http://angularjs.org/) under "Wire up a Backend". Instead of Firebase, I'm using WebSQL via Jaydata providers.
I have a WebSQL database called InspecTechDB with two tables, Organizations and Customers. There is a parent/child relationship between the two on OrganizationID. This is from my model:
$data.Entity.extend('Customer', {
'CustomerID': { 'key': true, 'type': 'Edm.Guid', 'nullable': false },
'OrganizationID': { 'type': 'Edm.Guid', 'nullable': false, 'required': true },
'CustomerName': { 'type': 'Edm.String' },
'Organization': { 'type': 'Organization', 'inverseProperty': '$$unbound' }
});
$data.Entity.extend('Organization', {
'OrganizationID': { 'key': true, 'type': 'Edm.Guid', 'nullable': false, 'required': true },
'OrganizationName': { 'type': 'Edm.String' },
'Customers': { 'type': 'Array', 'elementType': 'Customer', 'inverseProperty': '$$unbound' }
});
$data.EntityContext.extend('InspecTechDB', {
'Customers': { type: $data.EntitySet, elementType: Customer },
'Organizations': { type: $data.EntitySet, elementType: Organization }
});
I have 3 template views: OrganizationIndex.html, CustomerIndex.html, and CustomerEdit.html. The CustomerEdit.html is the one I'm having issues with:
<form name="myForm">
<div class="form-group">
<label>OrganizationID</label>
<input type="text" class="form-control" placeholder="OrganizationID" name="OrganizationID" ng-model="customer.OrganizationID" required>
<span ng-show="myForm.name.$error.required" class="help-inline">
Required
</span>
</div>
<div class="form-group" ng-class="{error: myForm.name.$invalid}">
<label>Name</label>
<input type="text" class="form-control" name="CustomerName" ng-model="customer.CustomerName" required>
<span ng-show="myForm.name.$error.required" class="help-inline">
Required
</span>
</div>
</form>
I've included my entire js file here:
var app = angular.module('AngularJaydataApp', ['ngRoute', 'jaydata']);
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
controller: 'OrganizationIndex',
templateUrl: 'OrganizationIndex.html'
})
.when('/CustomerIndex/:id', {
controller: 'CustomerIndex',
templateUrl: 'CustomerIndex.html'
})
.when('/CustomerEdit/:id', {
controller: 'CustomerEdit',
templateUrl: 'CustomerEdit.html'
})
.otherwise({
redirectTo: '/'
});
});
var localDB = new InspecTechDB({
name: 'local',
databaseName: 'InspecTech'
});
app.controller('OrganizationIndex', function ($scope, $data){
//wait until the localDB is ready, then get the Organizations
$.when(localDB.onReady())
.then(function () {
$scope.inspectechdb = localDB;
$scope.organizations = localDB.Organizations.toLiveArray();
});
});
app.controller('CustomerIndex', function ($scope, $data, $routeParams) {
$.when(localDB.onReady())
.then(function () {
$scope.inspectechdb = localDB;
$scope.Customers = $scope.inspectechdb
.Customers
.filter('OrganizationID', '==', $routeParams.id)
.toLiveArray();
});
});
app.controller('CustomerEdit', function ($scope, $data, $routeParams) {
var customerID = $routeParams.id;
$.when(localDB.onReady())
.then(function () {
$scope.inspectechdb = localDB;
$scope.inspectechdb.Customers.single(function (customer) {
return customer.CustomerID == this.Id;
},
{Id: customerID},
function (customer) {
$scope.customer = customer;
console.dir(customer);
});
});
console.log('this entry s/b after the customer console entry');
});
I can successfully navigate to each of the views and populate the OrganziationList.html template from my database as shown in the above code. I've set the Organization list up so that when I click the Organization entry on my view then the CustomerIndex.html view is loaded and bound to my customer list. This works fine. I've also set it up so that when I click a customer entry on the CustomerIndex view then the CustomerEdit.html view is loaded and here is where I get lost. The view appears just fine, but the form is not bound when the view is loaded, and I understand why (I think). It seems to be b/c angular is binding the form before my $scope.customer is populated. Evidence of this is the console log:
this entry s/b after the customer console entry bind.js:68
Customer
My question is this: Why do the OrganzationList and CustomerList views populate correctly and the CustomerEdit form does not and what can be done about it?
UPDATE
For anyone interested, I made it work by modifying the CustomerEdit controller per the accepted answer:
app.controller('CustomerEdit', function ($scope, $data, $routeParams) {
var customerID = $routeParams.id;
$.when(localDB.onReady())
.then(function () {
$scope.inspectechdb = localDB;
$scope.inspectechdb.Customers.single(function (customer) {
return customer.CustomerID == this.Id;
},
{ Id: customerID },
function (customer) {
$scope.$apply(function () {
$scope.customer = customer;
});
});
});
});
Angular has no idea that it should update the form. When you call tolivearray jaydata manages this for you. Calling single does not.
One way of solving it is that you call apply yourself when you updated the scope.
A better way would be to pass the entity instead of loading it, since it's already loaded.

Resources