AngularJS: Update JSON in modal with specific key - javascript

What's the best practice to update json in view with specific key.
In my case, i want to update feedback from 'not answered' to 'answered' .
[
{
"id": "34",
"mac_address": "cd:9e:17:64:1b:42",
"question": "Help me",
"time": "2016-03-16 16:22:08",
"is_answered": false
}
]
to
[
{
"id": "34",
"mac_address": "cd:9e:17:64:1b:42",
"question": "Help me",
"time": "2016-03-16 16:25:29",
"is_answered": true
}
]
There is some list my customer feedbacks:
<div class="parent" ng-repeat="customer in customers">
<h2>{{customer.id}}</h2>
<p>{{customer.question}}</p>
<h4 ng-show="{{customer.is_answered}}">Answered</h4>
<h4 ng-show="!{{customer.is_answered}}">Not Answered</h4>
<button ng-show="!{{customer.is_answered}}" ng-click="showModal()">Reply</button>
</div>
When i click reply button,then appear modal with some inputs to response my customer complaints.
<div id="modal">
<textarea placeholder=""response></textarea>
<button ng-click="submit()">Reply</button>
</div>
i want to update based of feedback id, and again, what the best practice how to do it?

You can pass the customer object with showModal call.
<div class="parent" ng-repeat="customer in customers">
<h2>{{customer.id}}</h2>
...
<button ng-show="!{{customer.is_answered}}" ng-click="showModal(customer)">Reply</button>
</div>
Inside your controller, save this passed in customer. Once modal closed, update is_answered property of that customer.
$scope.showModal = function (customer) {
var selected_customer = customer;
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
customer: customer
});
modalInstance.result.then(function () {
selected_customer.is_answered = true;
}
};

Found my solution, based on Pass input value to $mdDialog.
vm.showModal = function(e, message) {
$mdDialog.show({
clickOutsideToClose:true,
// locals:{ name: 'Bob'},
controller: function ($mdDialog) {
var vm = this;
vm.message = {};
vm.message = message;
$scope.hide = function () {
$mdDialog.hide();
};
$scope.cancel = function () {
$mdDialog.cancel();
};
},
controllerAs: 'modal',
templateUrl: 'feedbackForm.html',
parent: angular.element(document.body),
targetEvent: e,
});
};
In my view :
<h5 style="">{{modal.message.id}}</h5>
Thank you guys

Related

Angular Modal Text Boxes Not Getting Populated with ngModel

I have a table with TV show data on it. I populate the table with dir-paginate/ng-repeat and I can click a row to open a modal to be able to edit the show but the ng-model data is not loading on the text boxes within that modal.
<tr id='schedule_row' class='hover_click_cell' dir-paginate='tv_show in tv_shows | orderBy:sortType:sortReverse | itemsPerPage:10'>
<td class='center_text clickable_cell cell_width' ng-click='alter_show(tv_show)'>{{tv_show.show_name}}</td>
When clicked, it calls the function alter_show()
$scope.alter_show = function(show)
{
$scope.edit_show = show;
var modalInstance = $uibModal.open ({ animation: $controller.animationsEnabled,
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
templateUrl: 'edit_tv_show.html',
controller: 'EditTvShowCtrl',
controllerAs: '$controller',
size: 'sm',
backdrop: 'static',
keyboard: false
});
modalInstance.result.then(function (action)
{
},
function () {
});
}
The data passed looks like this in JSON form:
{"watched":false,"id":1,"show_name":"The Walking Dead","season":1,"episode":1,"season_episode":"Season 1, Episode 1","$$hashKey":"object:4"}
I pass in the show details and set it to the $scope.edit_show object. The data being passed on is not empty but when the modal is opened, the text boxes aren't populated. These are the input boxes:
$scope.edit_show = {
show_name: '',
season: 0,
episode: 0,
watched: 0
};
<div class='form-group'>
<label for='show_name'>Show Name:</label>
<input type='text' class='form-control' id='edit_show_name' ng-model='edit_show.show_name'>
</div>
<div class='form-group'>
<label for='season'>Season:</label>
<input type='number' class='form-control' id='edit_season' ng-model='edit_show.season'>
</div>
How can I get this to populate the text box with the details from the row that has been clicked?
I've manage to figure it out using resolve for the modalInstance.
$scope.alter_show = function(show)
{
var modalInstance = $uibModal.open ({ animation: $controller.animationsEnabled,
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
templateUrl: 'edit_tv_show.html',
controller: 'EditTvShowCtrl',
controllerAs: '$controller',
size: 'sm',
backdrop: 'static',
keyboard: false,
resolve: { tv_show : function() { return show; } }
});
modalInstance.result.then(function (action)
{
},
function () {
});
}
angular.module('ui.bootstrap').controller('EditTvShowCtrl', function ($uibModalInstance, $scope, tv_show)
{
var $controller = this;
$scope.edit = tv_show;
});

Passing ng-repeat data into another function

I wish to pass the detail of an order displayed in an ng-repeat to another function in my controller. I have it working with the first item in my array. How can I expand to display whichever order I have on that page?
When you click on the detail button it creates the required URL, I need this to be created whichever order is currently displayed on the detail page. Working with the first item in the array, can it be expanded to other orders?
https://plnkr.co/edit/nASmvcPakxKpRXDsfKnW?p=catalogue
app.js
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('starter', ['ionic','ngCordova'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
if(window.cordova && window.cordova.plugins.Keyboard) {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
// Don't remove this line unless you know what you are doing. It stops the viewport
// from snapping when text inputs are focused. Ionic handles this internally for
// a much nicer keyboard experience.
cordova.plugins.Keyboard.disableScroll(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('tabs', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('tabs.home', {
url: '/home',
views: {
'home-tab' : {
templateUrl: 'templates/home.html'
}
}
})
.state('tabs.list', {
url: '/list',
views: {
'list-tab' : {
templateUrl: 'templates/list.html',
controller: 'ListController'
}
}
})
.state('tabs.detail', {
url: '/list/:aId',
views: {
'list-tab' : {
templateUrl: 'templates/detail.html',
controller: 'ListController'
}
}
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/home');
})
.controller('ListController', ['$scope', '$http', '$state','$cordovaBluetoothSerial', '$window', '$location', function($scope, $http, $state, $cordovaBluetoothSerial, $window, $location) {
$http.get('js/aboDATAONLY.json').success(function(data) {
$scope.orders = data;
$scope.whichorder = $state.params.aId;
})
$scope.orders = [];
function onPay() {
var itemsArr = [];
var invoice = {};
var myItems = {};
var myItem = {};
var order = $scope.orders[0];
myItem['name'] = order.bkev_name;
myItem['description'] = "A robotic ball that can be controlled via apps";
myItem['quantity'] = bkor_seatcount;
myItem['unitPrice'] = order.bkor_subtotal;
myItem['taxRate'] = '0.0';
myItem['taxName'] = 'Tax';
itemsArr.push(myItem);
myItems['item'] = itemsArr;
invoice['itemList'] = myItems;
invoice['paymentTerms'] = 'DueOnReceipt';
invoice['currencyCode'] = 'GBP';
invoice['discountPercent'] = '0';
invoice['merchantEmail'] ='email#email.com';
invoice['payerEmail'] = 'foo#bar.com';
var returnUrl = order.bkor_seatcount;
var retUrl = encodeURIComponent(returnUrl + "?{result}?Type={Type}&InvoiceId={InvoiceId}&Tip={Tip}&Email={Email}&TxId={TxId}");
//var pphereUrl = "paypalhere://takePayment/?returnUrl={{returnUrl}}&invoice=%7B%22merchantEmail%22%3A%22{{merchantEmails}}%22,%22payerEmail%22%3A%22{{payerEmails}}%22,%22itemList%22%3A%7B%22item%22%3A%5B%7B%22name%22%3A%22{{name}}%22,%22description%22%3A%22{{description}}%22,%22quantity%22%3A%221.0%22,%22unitPrice%22%3A%22{{price}}%22,%22taxName%22%3A%22Tax%22,%22taxRate%22%3A%220.0%22%7D%5D%7D,%22currencyCode%22%3A%22{{currency}}%22,%22paymentTerms%22%3A%22DueOnReceipt%22,%22discountPercent%22%3A%220.0%22%7D";
var pphereUrl = "paypalhere://takePayment/v2?returnUrl=" + retUrl;
pphereUrl = pphereUrl + "&accepted=cash,card,paypal";
pphereUrl = pphereUrl + "&step=choosePayment";
pphereUrl = pphereUrl + '&invoice=' + escape(JSON.stringify(invoice));
console.log(pphereUrl);
return pphereUrl;
}
$scope.pay = function () {
var url = onPay();
window.open(url, "_system");
}
}]);
detail.html
<ion-header-bar class="bar-dark">
<h2 class="title">Order Detail</h1>
</ion-header-bar>
<ion-view>
<ion-content class="has-subheader">
<ion-list class="list-inset">
<ion-item class="item-text-wrap"
ng-repeat="order in orders | filter: { bkor_user: whichorder }">
<h1>Production Name: {{order.bkev_name}}</h1>
<h3>Seatcount: {{order.bkor_seatcount}}</h3>
<h1>Order Subtotal: £{{order.bkor_subtotal}}</h1>
</ion-item>
<button class="button button-block button-dark" ng-click="pay();">Pay Here</button>
</ion-list>
</ion-content>
</ion-view>
JSON data
[
{
"bkor_status": "A",
"bkor_datedmy": "08-02-2016",
"bkor_event": "34",
"bkor_user": "4028",
"bkev_name": "U2 Tribute",
"bkor_seatcount": "5",
"bkor_paymethod": "H",
"bkpay_short": "Cash",
"bkpay_status": "A",
"bkor_paid": "Y",
"bkor_payamount": "44.00",
"bkor_paiddatedmy": "08-02-2016",
"bkor_delivery": "N",
"bkdel_short": "Given",
"bkor_sent": "N",
"bkor_sentdatedmy": null,
"bkor_subtotal": "44.00",
"bkor_bookingfee": "0.00",
"estCardFee": "2.00",
"bkor_handling": "0.00",
"bkor_discount": "0.00",
"bkor_adjustment": "0.00"
},
{
"bkor_status": "A",
"bkor_datedmy": "16-02-2016",
"bkor_event": "35",
"bkor_user": "5001",
"bkev_name": "Fleetwood Mac Tribute",
"bkor_seatcount": "3",
"bkor_paymethod": "H",
"bkpay_short": "Card",
"bkpay_status": "A",
"bkor_paid": "Y",
"bkor_payamount": "28.00",
"bkor_paiddatedmy": "08-02-2016",
"bkor_delivery": "N",
"bkdel_short": "Given",
"bkor_sent": "N",
"bkor_sentdatedmy": null,
"bkor_subtotal": "28.00",
"bkor_bookingfee": "0.00",
"estCardFee": "2.00",
"bkor_handling": "0.00",
"bkor_discount": "0.00",
"bkor_adjustment": "0.00"
}
]
Move the button inside the ng-repeat loop and pass the order to your pay() scope function and then you can pass it to onPay() and not use the hardcoded var order = $scope.orders[0];
HTML
<ion-item class="item-text-wrap"
ng-repeat="order in orders | filter: { bkor_user: whichorder }">
<h1>Production Name: {{order.bkev_name}}</h1>
<h3>Seatcount: {{order.bkor_seatcount}}</h3>
<h1>Order Subtotal: £{{order.bkor_subtotal}}</h1>
<button class="button button-block button-dark" ng-click="pay(order);">Pay Here</button> <-- move this here and pass 'order'
</ion-item>
Controller
function onPay(order) {
var itemsArr = [];
var invoice = {};
var myItems = {};
var myItem = {};
// var order = $scope.orders[0]; <-- remove this
[ ... ]
}
$scope.pay = function (order) {
var url = onPay(order); <-- pass order
window.open(url, "_system");
}

error with using resolve angular-bootstrap-ui

I am having difficulties combining both the editing of a current contact and the creation of a new contact. I am able to edit the contact that I click on, however, when I try and click on add new address the following error message -
angular.js:13424 Error: [$injector:unpr] http://errors.angularjs.org/1.5.3/$injector/unpr?p0=editIndexProvider%20%3C-%20editIndex%20%3C-%20ModalCtrl
This is due to using resolve based on the answer here
Factory
'use strict';
var app = angular.module('testApp', ['ngRoute','ui.bootstrap']);
app.factory('addressFactory', function(){
var addressFactory = {};
addressFactory.addressBook = [];
addressFactory.saveAddress = function(name, address){
addressFactory.addressBook.push({
name: name,
address: address
});
};
addressFactory.updateAddress = function(name, address, index){
addressFactory.addressBook[index] = {
name: name,
address: address
};
};
return addressFactory;
})
CONTROLLERS
.app.controller('testCtrl', ['$uibModal', 'addressFactory', function ($uibModal, addressFactory) {
var testCtrl = this;
this.addressBook = addressFactory.addressBook;
this.open = function () {
touchnoteCtrl.modalInstance = $uibModal.open({
templateUrl: 'app/views/partials/add-address.html',
controller: 'ModalCtrl',
controllerAs:'ctrl'
});
}
this.openEdit = function(index) {
touchnoteCtrl.modalInstance = $uibModal.open({
templateUrl: 'app/views/partials/edit-address.html',
controller: 'ModalCtrl',
controllerAs:'ctrl',
resolve: {
editIndex: function () {
return index;
}
}
});
}
}])
.controller('ModalCtrl', ['$uibModalInstance','addressFactory','editIndex', function ($uibModalInstance,addressFactory, editIndex) {
this.addressBook = addressFactory.addressBook;
this.saveAddress = function( name, address) {
addressFactory.saveAddress( name, address);
$uibModalInstance.dismiss('cancel');
}
this.getIndex = editIndex;
console.log(this.getIndex)
this.updateAddress = function(name, address, index) {
addressFactory.updateAddress( name, address, index);
}
this.cancelAddress = function () {
$uibModalInstance.dismiss('cancel');
};
}]);
HTML
home.html
<a ng-click="ctrl.open()">Enter new address</a>
<div ng-repeat="contact in ctrl.addressBook track by $index">
<p class="contactName">{{contact.name}}</p>
<p class="contactAddress">{{contact.address}}</p>
<button ng-click="ctrl.openEdit($index)">Edit Contact</button>
</div>
form.html
<form>
<input ng-model="ctrl.name" type="text">
<input ng-model="ctrl.address" type="text">
</form>
edit-address.html
<h3>Edit address</h3>
<div ng-include="'app/views/partials/form.html'"></div>
<div>
<button ng-click="ctrl.cancelAddress()">Cancel</button>
<button ng-click="ctrl.updateAddress(ctrl.name, ctrl.address, ctrl.getIndex)">Save</button>
</div>
add-address.html
<h3>Add address</h3>
<div ng-include="'app/views/partials/form.html'"></div>
<div>
<button ng-click="ctrl.cancelAddress()">Cancel</button>
<button ng-click="ctrl.addAddress(ctrl.name, ctrl.address)">Save</button>
</div>
You use the same ModalCtrl for both the open and the openEdit function. The open function does not have a resolve parameter. This way, angular cannot resolve the injected editIndex. Try this:
this.open = function () {
touchnoteCtrl.modalInstance = $uibModal.open({
templateUrl: 'app/views/partials/add-address.html',
controller: 'ModalCtrl',
controllerAs:'ctrl',
resolve: {
editIndex: function () {
return undefined;
}
}
});
}
I think you simply miss a module dependency to angular.ui.bootstrap...

Angular Directive Element dynamic Template fields with its updated model value from controller?

I have <superhero> directive which has two directive
web-buttons to take of the form validation and post the updated
ngModel value to respective controller
fieldMap directive to generate the dynamic fields by object we are passing from respective controller
Here is the example which i have worked
directive attribute called saveFormFn will tell the button to call which function to invoked using enter attribute directive.
For example. After click save button it will call the function 'Ctrl1saveFormFn' from controller Ctrl1 .This function will make ajax post to save the form fields.
After updating the text fields with some content and click save,I have passed the current scope of the directive to respective controller (see console log). i could not get the updated fielddata value from current Scope.
$scope.Ctrl1saveFormFn = function(item){
_.each(item,function(currentScope){
console.log(currentScope)
// here i want to collect the form data with updated fielddata values
})
}
I am beginner.Am i on right path? Please advice
I've re-written your code because it was pretty hard to understand.
I would do it like this:
Use ng-include to load the template of your buttons. That's loading the control buttons edit and save.
Save your data in a variable in the superhero directive. Maybe it would be even better to store it in a separate service/factory.
Create a directive customForm that will create a form based on the supplied model that you're passing to its scope.
The main application logic is in the superhero directive because it is adding the controls save/edit to the DOM. If saving/editing is not only related to the superhero it would be better to do it in your main controller.
Please have a look at the demo below or in this jsfiddle.
angular.module('demoApp', [])
.directive('superhero', Superhero)
.directive('customForm', CustomForm)
.controller('mainController', MainController);
function Superhero() {
return {
restrict: 'E',
scope: {
formModel: "=",
},
template: '<div class="hero"><div ng-include="\'web-buttons.html\'"></div><custom-form model="formModel"></custom-form></div>',
controllerAs: 'superHeroCtrl',
controller: function ($scope) {
var self = this;
console.log('controller directive');
angular.extend(this, {
abilities: [],
editMode: false,
addStrength: function (data) {
self.abilities.push(data);
},
getStrength: function () {
return self.abilities;
},
showSave: function() {
self.editMode = true;
$scope.formModel.editMode = true;
},
hideSave: function() {
self.editMode = false;
$scope.formModel.editMode = false;
},
save: function() {
self.addStrength('can fly');
console.log(self.getStrength());
console.log('saving data now of form now...', $scope.formModel.data);
alert('saving data of form now: ' + self.getStrength()[0] + ' - ' + JSON.stringify( $scope.formModel.data, null, 2));
self.hideSave();
}
});
}
}
}
function CustomForm() {
return {
restrict: 'EA',
scope: {
model: '='
},
template: '<div ng-if="model.editMode" ng-repeat="formElement in model.fields" ng-include="formElement.template.url"></div>'
}
}
function MainController() {
this.normalForm = {
editMode: false,
data: {
},
fields: {
'NAME':{
template: {
url: 'customForms/text.html',
type: 'edit' // not sure for what it is needed
},
label: 'First name',
id: "NAME",
placeholder : "First Name",
fieldData: "NAME",
key : 'first_name'
},
'LNAME': {
template: {
url: 'customForms/text.html',
type: 'edit' // not sure for what it is needed
},
label: "Last Name",
placeholder : "Last Name",
id: "LNAME",
key : 'last_name'
}
}
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="mainController as mainCtrl">
<script type="text/ng-template" id="customForms/text.html">
<label for="{{formElement.id}}">{{formElement.label}}</label>
<input ng-model="model.data[formElement.key]" placeholder="{{formElement.placeholder}}" id="formElement.id"/>
</script>
<script type="text/ng-template" id="web-buttons.html">
<button ng-click="superHeroCtrl.showSave()" ng-if="!superHeroCtrl.editMode">edit</button>
<button ng-if="superHeroCtrl.editMode" ng-click="superHeroCtrl.save()">save</button>
</script>
<superhero form-model="mainCtrl.normalForm"></superhero>
<h3>debug output:</h3>
<pre>
{{mainCtrl.normalForm |json}}
</pre>
</div>

move to different pages based on the checked radio button

i have this form and it has 3 ionic radio buttons used.Is there a way to a move to different pages according to the radio buttons that are selected.For ex: my radio buttons are named
1.USO
2.OASO
3.TFTSO
I want to move to a different page if i select USO , and to another different page if i choose OASO and so on. I want to move only after i click the 'Proceed' Button that i've implemented in my code.
This is how i've implemented by radio buttons and proceed button in html
<label class="labelColor">
<h5><b>Select Standing Order Type</b></h5>
</label>
<div class="list">
<ion-radio ng-repeat="item in clientSideList"
ng-value="item.value"
ng-model="data.clientSide">
{{ item.text }}
</ion-radio>
</div>
<!-- BUTTONS -->
<div class="col"
style="text-align: center">
<button align="left"
class="button button-block button-reset"
style="display:
inline-block;width:100px;text-align:center "
type="reset"
ng-click="submitted = false; reset()"
padding-top="true">
Reset
</button>
<button class="button button-block button-positive"
style="display: inline-block;width:100px "
ng-click="submitted=true; "padding-top="true">
Proceed
</button>
</div>
my angularjs
.controller('OrderCtrl', function($scope,$state) {
$scope.clientSideList = [
{ text: "Utility Standing Order", value: "uso" },
{ text: "Own Account Standing Order", value: "oaso" },
{ text: "Third Party Fund Transfer Standing Order", value: "tpftso" }
];
$scope.data = {
clientSide: 'uso'
};
})
My controller
.controller('OrderCtrl', function($scope,$state, $http, $ionicPopup) {
$scope.clientSideList = [
{ text: "Utility Standing Order", value: "uso" },
{ text: "Own Account Standing Order", value: "oaso" },
{ text: "Third Party Fund Transfer Standing Order", value: "tpftso" }
];
$scope.data = {
clientSide: 'uso'
};
$scope.move = function () {
var path;
switch($scope.data.clientSide) {
case 'uso': path = '/so/utilitystanding'; break;
case 'oaso': path = '/so/ownstandingorder'; break;
case 'tpftso': path = '/so/thirdstandingorder'; break;
}
$state.go(app.standing);
};
})
.controller('utilityStandingCtrl', function($scope,$state) {
});
Try to add ng-click to your Proceed button and define function which will analyse value of your selected data.clientSide and then call $location.path(url). You need to inject $location service into your controller.
JavaScript:
$scope.goSomewhere = function () {
var path;
switch($scope.data.clientSide) {
case 'uso': path = '/uso'; break;
case 'oaso': path = '/oaso'; break;
case 'tpftso': path = '/tpftso'; break;
}
$location.path(path);
};
And HTML:
<button ng-click="goSomewhere()">Proceed</button>
Demo: http://plnkr.co/edit/jawx0OivVmu2EyNmAbR9?p=preview
Edit
My answer above is related to angular-route, not to ui-router. In the last you need to use all the same code except of function call. Instead of location.path() it must me
$state.go(yourStateName)
Please note, not url, but state name.
Edit2
Here is code for ionic framework (almost the same) + settings of application.
Config:
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('main', {
url: "/main",
templateUrl: 'main.html'
})
.state('usoStateName', {
url: '/uso',
templateUrl: 'page.html',
controller: 'usoCtrl'
})
.state('oasoStateName', {
url: '/oaso',
templateUrl: 'page.html',
controller: 'oasoCtrl'
})
.state('tpftsoStateName', {
url: '/tpftso',
templateUrl: 'page.html',
controller: 'tpftsoCtrl'
});
$urlRouterProvider.otherwise('/main');
});
And function:
$scope.goSomewhere = function () {
var path;
switch($scope.data.clientSide) {
case 'uso': path = 'usoStateName'; break;
case 'oaso': path = 'oasoStateName'; break;
case 'tpftso': path = 'tpftsoStateName'; break;
}
$state.go(path);
};
Demo: http://plnkr.co/edit/0sk3dECPNm35HgMqiprt?p=preview
Instead of {{ item.text }}
Try something like this:
a href=""#/viewName/{{item.text }}"}">{{ item.text }}

Categories