I have a small web application which uses both laravel and stripe.. In my view I give the ability to the logged in user to top up their account. On the view I have 5 packages.
1 Credit
10 Credits etc
I've got stripe to take the right amount from the users card which is great, however i'm struggling passing the data-quantity through to my controller which would add the credits.
View (Just for example I've included just the one package)
<div class="col-sm-6 col-lg-2">
<!-- Small Package -->
<div class="block block-bordered text-center">
<div class="block-header">
<h3 class="block-title">Super!</h3>
</div>
<div class="block-content block-content-full bg-primary-dark">
<div class="h1 font-w700 text-white push-10">200</div>
<div class="h5 font-w300 text-white">Credits</div>
</div>
<div class="block-content">
<table class="table table-borderless table-condensed">
<tbody>
<tr>
<td><strong>£1.80</strong> each <small class="text-muted">ex VAT</small></td>
</tr>
</tbody>
</table>
</div>
<div class="block-content bg-gray-lighter">
<table class="table table-borderless table-condensed">
<tbody>
<tr>
<td>
<button id="" class="btn btn-block btn-success btn-default customButton" data-price="43200" data-credits="200" data-title="200 x Credits">Pay by Card</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- END Small Package -->
</div>
Javascript handling the click event which captures the data-attr against each button.. i.e. the value, the title and quantity.
<script>
var handler = StripeCheckout.configure({
key: 'pk_test_code',
image: '{{ url() }}/assets/img/stripe-icon.jpg',
locale: 'auto',
token: function(token) {
$.post('/call/topup', {token: token}, function(data) {
alert('TOPPED UP!');
});
}
});
$('.customButton').on('click', function(e) {
handler.open({
description: $(this).attr('data-title'),
currency: "gbp",
amount: $(this).attr('data-price')
});
e.preventDefault();
});
// Close Checkout on page navigation
$(window).on('popstate', function() {
handler.close();
});
</script>
Controller which handles the request and charges the card.
public function topup(Request $request)
{
$token = $request->token['id'];
$user = User::FindOrFail(1);
$user->charge(6000, [
'source' => $token,
'currency' => 'gbp',
'receipt_email' => $user->email,
]);
return $request->token;
}
I haven't yet included the topping up the account because I can't figure out how to get the data-quantity to the controller :( help.
Related
I'm new to vue js and trying to use it with a bootstrap modal to view more data. My scenario is a table with multiple records and a button to see in depth details for the clicked record in a bootstrap modal. After clicking the first button it caches and doesn't update it while selecting another button for different details.
Does anyone see what I'm doing wrong?
(It's a combination of Laravel, jQuery and VueJS)
HTML Table:
<table class="table table-striped">
<thead>
<tr>
<th>E-mail address</th>
<th>Status</th>
<th>Sent at</th>
<th>Expires in</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td class="v-align-middle">
john#doe.example
</td>
<td class="v-align-middle">
<span class="label label-default">
pending
</span>
</td>
<td class="v-align-middle">
2017-06-05 17:59:15
</td>
<td class="v-align-middle">
29 days
</td>
<td>
<div class="btn-group pull-right">
<a href="#" class="btn btn-default" data-toggle="modal" data-target="#inviteDetailsModal" data-email="john#doe.example">
<i class="fa fa-eye"></i>
</a>
</div>
</td>
</tr>
<tr>
<td class="v-align-middle">
jane#doe.example
</td>
<td class="v-align-middle">
<span class="label label-default">
pending
</span>
</td>
<td class="v-align-middle">
2017-06-05 13:27:25
</td>
<td class="v-align-middle">
29 days
</td>
<td>
<div class="btn-group pull-right">
<a href="#" class="btn btn-default" data-toggle="modal" data-target="#inviteDetailsModal" data-email="jane#doe.example">
<i class="fa fa-eye"></i>
</a>
</div>
</td>
</tr>
</tbody>
JavaScript:
$('[data-target="#inviteDetailsModal"]').on('click', function () {
let email = $(this).data('email'),
baseUrl = $('html').data('base');
Vue.component('invite-details', {
data: function () {
return {
email: null,
token: null,
logs: [],
expires: null
}
},
methods: {
update: function (data) {
this.email = data['email'];
this.token = data['token'];
this.logs = data['logs'];
this.expires = data['expires'];
},
fetchData: function () {
this.$http.get(baseUrl + '/system/invites/' + email + '/details')
.then(response => {
this.update(response.body);
}, response => {
console.log('whoops something went wrong');
});
}
},
mounted: function () {
this.$el.addEventListener('shown.bs.modal', this.fetchData());
},
beforeDestroy: function () {
this.$el.removeEventListener('shown.bs.modal', this.fetchData());
}
});
new Vue({
el: '#inviteDetailsModal'
});
});
The bootstrap modal:
<div class="modal fade slide-up" id="inviteDetailsModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content-wrapper">
<invite-details inline-template>
<div class="modal-content" id="details">
<div class="modal-header clearfix text-left">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<i class="pg-close fs-14"></i>
</button>
<h5>
Invite details for <span class="semi-bold">#{{ email }}</span>
</h5>
<p class="p-b-10">
<span data-tooltip="true" data-placement="bottom" title="token">
<em>#{{ token }}</em>
</span>
</p>
</div>
<div class="modal-body">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Sent at</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr v-for="log in logs">
<td>#{{ log.number }}</td>
<td>#{{ log.sentAt }}</td>
<td>#{{ log.status }}</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer text-center">
<span class="hint-text">
<em>expires in <strong>#{{ expires }}</strong> days</em>
</span>
</div>
</div>
</invite-details>
</div>
</div>
Alright I dug in deep to get this working and went the extra mile because you mentioned your were new at VueJS. I recognised my old self in your code where you go into VueJS with a JQuery mindset ;-)
First few quick notes before dropping the full code:
Use the table DB row's integer ID to reference the user everywhere.
This way when the email is updated, you still know who it is in the
frontend. By examining the code I saw that the email can change
(because it's an updateable data property, but it's also used in
your GET request: baseUrl + '/system/invites/' + email +
'/details'
Subsequently, you can use this ID to easily generate unique instances
of your modal :-) This is the way you want to be working with VueJS!
Since you're using the same data in multiple places, have a look at
Vuex for a store. It may look daunting at first but it's great once
you get to grips with it. In your case, the same dataset would be
used for the original table and the modals. If one updates,
everything updates!
With Vuex you can trigger updates from anywhere. Right now the data
gets updated every time the eye button is clicked. However, this is
pretty hacky as I've made the button part of the modal's template,
and every time it gets clicked it calls fetchData() (check the
console). What you want to do ideally is use Vuex and generate
everything from the single point of truth dataset. Currently, if the
modal's data is updated, the original table is not.
With VueJS it's just as easy to create your own modal. The upside of
this is less overhead in your code, as you can use v-if, so it
won't be loaded into the DOM unless actually required. And judging
from your current code, the details button would be clicked
occasionally.
Install VueJS debugger if you haven't already:
https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd,
it will help you 'see' under the hood.
Alright so now for the code! First, add this line to your app.js file:
import JaimyTable from './components/stackoverflow/JaimyTable.vue'
Right above the var app = new Vue({ line. And add it to your components, so you end up with something like this:
import JaimyTable from './components/stackoverflow/JaimyTable.vue'
var app = new Vue({
components: {
JaimyTable,
},
});
Here's the JaimyTable.vue file:
<template>
<div class="container">
<table class="table table-striped">
<thead>
<tr>
<th>E-mail address</th>
<th>Status</th>
<th>Sent at</th>
<th>Expires in</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td class="v-align-middle">
john#doe.example
</td>
<td class="v-align-middle">
<span class="label label-default">
pending
</span>
</td>
<td class="v-align-middle">
2017-06-05 17:59:15
</td>
<td class="v-align-middle">
29 days
</td>
<td>
<div class="btn-group pull-right">
<jaimy-modal id="1"></jaimy-modal>
</div>
</td>
</tr>
<tr>
<td class="v-align-middle">
jane#doe.example
</td>
<td class="v-align-middle">
<span class="label label-default">
pending
</span>
</td>
<td class="v-align-middle">
2017-06-05 13:27:25
</td>
<td class="v-align-middle">
29 days
</td>
<td>
<div class="btn-group pull-right">
<jaimy-modal id="2"></jaimy-modal>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import JaimyModal from './JaimyModal.vue'
export default {
components: { JaimyModal },
props: [],
mixins: [],
data: function () {
return {
//
}
},
computed: {
computed_variable() {
return '';
}
},
created() {
//
},
mounted() {
//
},
methods: {
//
},
watch: {
//
}
}
</script>
And please note the <jaimy-modal id="1"></jaimy-modal> lines. You probably want to use v-for to generate the all the <tr> rows automatically :) Make sure the id= corresponds to the ID in your database.
Now for the JaimyModal.vue where all the magic happens:
<template>
<div>
<a href="#" class="btn btn-default" data-toggle="modal" :data-target="'#inviteDetailsModal' + id" #click="fetchData()">
<i class="fa fa-eye"></i>
</a>
<div class="modal fade slide-up" :id="'inviteDetailsModal' + id" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content-wrapper">
<div class="modal-content" id="details">
<div class="modal-header clearfix text-left">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<i class="pg-close fs-14"></i>
</button>
<h5>
Invite details for <span class="semi-bold">{{ email }}</span>
</h5>
<p class="p-b-10">
<span data-tooltip="true" data-placement="bottom" title="token">
<em>{{ token }}</em>
</span>
</p>
</div>
<div class="modal-body">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Sent at</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr v-for="log in logs">
<td>{{ log.number }}</td>
<td>{{ log.sentAt }}</td>
<td>{{ log.status }}</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer text-center">
<span class="hint-text">
<em>expires in <strong>{{ expires }}</strong> days</em>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['id'],
data: function () {
return {
email: null,
token: null,
logs: [],
expires: null,
baseUrl: 'https://yourbaseurl.com',
}
},
mounted: function () {
//
},
methods: {
update: function (data) {
this.email = data['email'];
this.token = data['token'];
this.logs = data['logs'];
this.expires = data['expires'];
},
fetchData: function () {
console.log('data fetched');
// Commented out for local purposes
// this.$http.get(this.baseUrl + '/system/invites/' + this.email + '/details')
// .then(response => {
// this.update(response.body);
// }, response => {
// console.log('whoops something went wrong');
// });
// Dummy data
this.update({
email: 'test#test ' + this.id + '.com',
token: 'token123123asdsasdasdasd',
logs: [
{
number: 1,
sentAt: '2017-01-01',
status: 'Ok',
},
{
number: 2,
sentAt: '2017-02-01',
status: 'Failed',
},
],
expires: '2017-10-01'
});
}
},
}
</script>
Important to note here is the :data-target="'#inviteDetailsModal' + id" part in the button, where the number corresponds to the id of the prop. By using the : you're making it an expression, and it resolves to a unique reference.
As you can see the setup is completely different than you had before. Where the modal is a nested component of your table row. Once you start thinking of Components as recurring parts of look and functionality, but with unique data within it, things will click fast. Think of it as Model in Laravel.
After a long time of being told that you need to separate design (CSS), mark-up (HTML) and functionality (JS), it's weird to have it all sitting there in 1 file. But embrace it, and you'll fall in love with VueJS :D
And give Vuex a look! The second you get multiple components that use and manipulate the same dataset, it's a god-send!
Ow and finally: the second you start thinking of using things like fn.trigger and whatnot, you're approaching VueJS wrong. Keep that in mind :) It has all the tools necessary for you to work with the page, and then some!
Happy coding!
Since you're using one modal component and are attempting to change its content based on the specific button in the table clicked, the mounted hook is only going to fire once when the component is initially mounted.
What you want is for the content to update each time the modal is shown.
First of, it looks like your component only needs one email prop. Move the rest of the props to be in the data method for the component, since (I'm assuming) they aren't being passed into the component:
props: ['email'],
data: function() {
return {
token: null,
logs: null,
expires: null,
}
}
Then, I would create a new method called fetchData to put the $http.get call in:
fetchData: function() {
this.$http.get('http://localhost:2000/system/invites/' + this.email + '/details')
.then(response => {
this.update(response.body);
}, response => {
console.log('whoops something went wrong');
});
}
In your modal component's mounted hook, add a listener to the bootstrap modal's show event using jQuery. And be sure to remove the listener in the component's beforeDestroy hook:
mounted() {
$(this.$el).on('shown.bs.modal', this.fetchData);
},
beforeDestroy() {
$(this.$el).off('shown.bs.modal', this.fetchData);
}
Now, every time the modal's show event fires, the $http.get request will fire based on the current value of the component's email property.
Here's an example fiddle.
while trying to implement a cart for my eshop I have noticed that initCartId and refreshCart are called recursively, causing the project to crash.
The problem is the same with this one but this cannot help me to identify where I use recursion.
The alerts from controller.js when I go to cart page are:
initCartId!!!
refreshCart!!!
calGrandTotal!!!
calGrandTotal!!!
calGrandTotal!!!
The first 2 alerts from calGrandTotal function looks like:
At this point I can see the StackOverFlowError at the console but the alerts continue to appear one more time with the following sequence:
initCartId!!!
refreshCart!!!
calGrandTotal!!!
cart.jsp
<%#taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%#include file="/WEB-INF/views/template/header.jsp"%>
<div class="container-wrapper">
<div class="container">
<section>
<div class="jumbotron">
<div class="container">
<h1>Cart</h1>
<p>All the selected products in your shopping cart</p>
</div>
</div>
</section>
<section class="container" ng-app="cartApp">
<div ng-controller="cartCtrl" ng-init="initCartId('${cartId}')">
<div>
<a class="btn btn-danger pull-left" ng-click="clearCart()"><span
class="glyphicon glyphicon-remove-sign"></span>Clear Cart</a>
</div>
<table class="table table-hover">
<tr>
<th>Product</th>
<th>Unit Price</th>
<th>Quantity</th>
<th>Price</th>
<th>Action</th>
</tr>
<tr ng-repeat="item in cart.cartItems">
<td>{{item.product.productName}}</td>
<td>{{item.product.productPrice}}</td>
<td>{{item.quantity}}</td>
<td>{{item.totalPrice}}</td>
<td><a href="#" class="label label-danger"
ng-click="removeFromCart(item.product.productId)"> <span
class="glyphicon glyphicon-remove"></span>remove
</a></td>
</tr>
<!-- <tr>
<th></th>
<th></th>
<th>Grand Total</th>
<th>{{calGrandTotal()}}</th>
<th></th>
</tr> -->
</table>
<a href="<spring:url value="/productList" />"
class="btn btn-default">Continue Shopping</a>
</div>
</section>
</div>
</div>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<script src="<c:url value="/resources/js/controller.js" /> "></script>
<%#include file="/WEB-INF/views/template/footer.jsp"%>
controller.js
var cartApp = angular.module ("cartApp", []);
cartApp.controller("cartCtrl", function ($scope, $http){
/* corresponding to the mapper at CartController with RequestMethod.GET */
/*
* /eMusicStore/rest/cart/'+$scope.cartId) get the cart data in Json format
* and with the success we use another function and the JSON format cart
* info will be stored into data and we pass into $scope
*/
$scope.refreshCart = function (cartId) {
alert("refreshCart!!!");
$http.get('/eMusicStore/rest/cart/'+$scope.cartId).success(function (data) {
$scope.cart=data;
});
};
$scope.clearCart = function () {
alert("clearCart!!!");
/*$http.delete('/eMusicStore/rest/cart/'+$scope.cartId).success($scope.refreshCart($scope.cartId));*/
$http.delete('/eMusicStore/rest/cart/'+$scope.cartId).success(function (data) {
$scope.refreshCart($scope.cartId);
});
};
$scope.initCartId = function (cartId) {
alert("initCartId!!!");
$scope.cartId = cartId;
/* alert("cartId:" + cartId);*/
$scope.refreshCart($scope.cartId);
};
$scope.addToCart = function (productId) {
alert("addToCart!!!");
$http.put('/eMusicStore/rest/cart/add/'+productId).success(function (data) {
/*$scope.refreshCart($http.get('/eMusicStore/rest/cart/cartId'));*/
alert("Product successfully added to the cart!");
});
};
$scope.removeFromCart = function (productId) {
alert("removeFromCart!!!");
$http.put('/eMusicStore/rest/cart/remove/'+productId).success(function (data) {
/*$scope.refreshCart($http.get('/eMusicStore/rest/cart/cartId'));*/
$scope.refreshCart($scope.cartId);
});
};
$scope.calGrandTotal = function () {
alert("calGrandTotal!!!");
var grandTotal=0;
for (var i=0; i<$scope.cart.cartItems.length; i++) {
grandTotal+=$scope.cart.cartItems[i].totalPrice;
}
return grandTotal;
};
});
I need help with displaying row data using modal when the row is clicked. At the
moment it displays on the next row. It has to display the same data as a modal. I also need help on the return list, how can use URI/URL or rather point to a JSON file in there and avoid hard-coded data. Attached is a piece of code that explains what I have.
Thanks!
<body>
<table ng-controller="UsersCtrl" class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="user in users" ng-click="selUser(user)">
<td>{{user.name}}</td>
<td>{{user.age}}</td>
</tr>
<tr ng-repeat-end ng-if="isSelected(user)">
<td colspan="2">{{user.desc}}{{user.name}}{{user.age}}</td>
<!-- display row details using modal -->
</tr>
</tbody>
</table>
<script>
angular.module('App',[])
.factory('Users',function(){
return {
query:function(){
return [
{name:'John',age:25,desc:'Software Developer at MacroSoft LLC'},
{name:'Jonatan',age:26,desc:'Professor at University of Tashkent'},
{name:'Nataly',age:27,desc:'Nurse at central hospital'},
{name:'Lucy',age:28,desc:'Teacher at district school'}
<!-- how do I use a URI/URL in here or point to a JSON File? -->
];
}
}
})
.controller('UsersCtrl',function($scope,Users){
$scope.users=Users.query();
$scope.selUser=function(user){
$scope.selected_user=user;
}
$scope.isSelected=function(user){
return $scope.selected_user===user;
}
});
You could just use a Modal trigger in the controller to get the content into modal.
You can take a look at Angular $http service to retrieve the json from a location.
var app = angular.module("sampleApp", []);
app.factory('Users', function() {
return {
query: function() {
return [{
name: 'John',
age: 25,
desc: 'Software Developer at MacroSoft LLC'
}, {
name: 'Jonatan',
age: 26,
desc: 'Professor at University of Tashkent'
}, {
name: 'Nataly',
age: 27,
desc: 'Nurse at central hospital'
}, {
name: 'Lucy',
age: 28,
desc: 'Teacher at district school'
}
<!-- how do I use a URI/URL in here or point to a JSON File? -->
];
}
}
})
.controller('UsersCtrl', function($scope, Users) {
});
app.controller("sampleController", ["$scope", "Users",
function($scope, Users) {
$scope.users = Users.query();
$scope.selUser = function(user) {
$scope.selected_user = user;
angular.element('#myModal').modal();
}
$scope.isSelected = function(user) {
return $scope.selected_user === user;
}
}
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div ng-app="sampleApp">
<div ng-controller="sampleController">
<table ng-controller="UsersCtrl" class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="user in users" ng-click="selUser(user)">
<td>{{user.name}}</td>
<td>{{user.age}}</td>
</tr>
</tbody>
</table>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
{{selected_user.desc}}{{selected_user.name}}{{selected_user.age}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
</div>
1st Question:
You need to open some popup modal to show the selected user . On your selUser() function you can open popup where selected_user data is shown. Also you have to remove second row in table body this makes no sense.
$scope.selUser=function(user){
$('#detail').modal('show');
$scope.selected_user=user;
}
<tr ng-repeat="user in users" ng-click="selUser(user)">
<td>{{user.name}}</td>
<td>{{user.age}}</td>
</tr>
2nd Question:
For querying data from JSON file your have to create a javascript file for ex : data.json and include this with script tag.
<script type="text/javascript" src="data.js"></script>
In data.js will include json for user
var data = [{ name: 'John', age: 25, desc: 'Software Developer at MacroSoft LLC' },
{ name: 'Jonatan', age: 26, desc: 'Professor at University of Tashkent' },
{ name: 'Nataly', age: 27, desc: 'Nurse at central hospital' },
{ name: 'Lucy', age: 28, desc: 'Teacher at district school' }];
In this way you will get the json from file.
My issue is when I load the page first time the angular is working pretty well. but when I try to use same thing when my html is loaded with ajax it is not working at all. nor I can see any relevant error in console.
javascript:
var myApp = angular.module('myApp', ['ngSanitize','ui.utils']);
myApp.controller('CtrlPerformanceByTrack', function($scope, $http) {
$http.get(site_url + 'performance/?method=get_performance_by_track_data').success(function(data, status) {
/*console.log(data.data);
data=[{"title":"title 1","length":"3:02","plays":4,"sales":2,"likes":8},
{"title":"title 1","length":"3:02","plays":4,"sales":2,"likes":8}]
console.log(data);*/
$scope.tracks = data.data;
}).error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
});
html:
<div data-ele="PerformanceByTrackApp" class="track-block" ng-controller="CtrlPerformanceByTrack">
<div class="title">
Performance by track
</div>
<div class="search-block">
<form>
<div class="content fr">
<div class="left-input">
<input type="text" class="form-control" placeholder="Search Track" ng-model="searchTrack">
</div>
<div class="right-icon-block">
<span class="icon-magnifying42 search-icon"></span>
</div>
</div>
</form>
<div class="clearfix"></div>
</div>
<div class="clearfix"></div>
<div class="table-block">
<table class="table table-striped table-responsive track-table">
<thead class="title">
<th style="width:50%;">Title</th>
<th style="width:13%;">Length</th>
<th style="width:13%;">Plays</th>
<th style="width:13%;">Sales</th>
<th style="width:14%;">Likes</th>
</thead>
<tr ng-repeat="item in tracks | filter:searchTrack">
<td>{{item.title}}</td>
<td>{{item.length}}</td>
<td>{{item.plays}}</td>
<td>{{item.sales}}</td>
<td>{{item.likes}}</td>
</tr>
</table>
</div>
</div>
the sample is at below url:
http://engagev2.ncryptedprojects.com/performance
to call the same page via ajax click performance tab at left.
If you're getting this partial HTML via AJAX, then it should be properly inserted. You have to use angular $compile service. Simplified example below.
...
var template = getTemplate();
var compiledElement = $compile(template)($scope);
element.append(compiledElement);
...
Here is the link https://docs.angularjs.org/api/ng/service/$compile
I have a print directive in a SPA that seems to lose its 2 way data binding after the first print function is ran. I am sure it has something to do with the cloning and appending of the element.
The Directive is as follows:
agency.directive("pasPrint", ['AgentModel','Dev',
function(agentModel, dev) {
var printSection = document.getElementById("printSection");
function printElement(elem) {
// clones the element you want to print
var domClone = elem.cloneNode(true);
if (!printSection) {
printSection = document.createElement("div");
printSection.id = "printSection";
document.body.appendChild(printSection);
} else {
printSection.innerHTML = "";
}
printSection.appendChild(domClone);
}
return {
restrict: 'A',
link: function($scope, $element, attrs) {
$scope.printModel = {};
$scope.today = new Date().toJSON().slice(0,10);
$element.on("click", function () {
var elemToPrint = document.getElementById(attrs.printElementId);
if (elemToPrint) {
printElement(elemToPrint);
window.print();
}
});
},
controller: ["$scope","$element", "AgentModel", function($scope, $element, agentModel) {
$scope.agentModel = agentModel;
}]
};
}]);
the model that is used in the entire module here is the agentModel.singleAgent which of course represents a single agent. this directive simply prints a cover sheet for an agents hard copy record. the first time we pull up an agents record the cover sheet prints correctly. when we load another agent the print preview show's the correctly updated agent information. in the agentModel.singleAgent 2 way binding (the same values being used in the printSection that gets printed. However the second print attempt also prints the first agent information and so does any other attempt to print any other agents, they all print the first agents data, even thought the singleAgent model has been updated properly.
the html from the print preview is below:
<div class="modal-header ng-scope">
<button type="button" class="close" aria-label="Close" data-ng- click="cancel()"><span aria-hidden="true"> × </span></button>
<h3 class="modal-title ng-binding"> Edit & Print Cover Sheet </h3>
</div>
<div class="modal-body">
<form class="inline-form">
<div class="form-group">
<label class="form-label" for="PRINT_DESC">File Description: </label>
<input class="input-medium" type="text" id="PRINT_DESC" name="PRINT_DESC" data-ng-model="printModel.PRINT_DESC" />
</div>
</form>
<div id="printPreview">
<table class="table table-cell-nowrap table-responsive">
<thead>
<tr>
<th colspan="2"><strong>Type: <em>{{printModel.PRINT_DESC}}</em></strong></th>
<th colspan="2" style="border: 1px #dadada dotted"><div class="clearfix pull-right"><strong>{{agentModel.singleAgent.AGENT_NUMBER}}</strong></div></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Agent Name: {{ agentModel.singleAgent.AGENT_LNAME }}, {{ agentModel.singleAgent.AGENT_FNAME }} </strong></td>
<td><strong>Agent #: {{ agentModel.singleAgent.AGENT_NUMBER }}</strong></td>
<td><strong>UID: {{ agentModel.singleAgent.AGENT_UID }}</strong></td>
<td></td>
</tr>
<tr><td colspan="4">Printed On: {{ today }} </td></tr>
</tbody>
</table>
</div>
<div id="printSection" class="col-md-12"><!-- place nothing in here except what should be printed. by default the content in the print section IS hidden -->
<table class="table table-cell-nowrap table-responsive printCoverFontSize">
<thead>
<tr>
<th colspan="2"><strong>Type: <em>{{printModel.PRINT_DESC}}</em></strong></th>
<th colspan="2" style="border: 1px #dadada dotted"><div class="clearfix pull-right"><strong>{{agentModel.singleAgent.AGENT_NUMBER}}</strong></div></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Agent Name: {{ agentModel.singleAgent.AGENT_LNAME }}, {{ agentModel.singleAgent.AGENT_FNAME }} </strong></td>
<td><strong>Agent #: {{ agentModel.singleAgent.AGENT_NUMBER }}</strong></td>
<td><strong>UID: {{ agentModel.singleAgent.AGENT_UID }}</strong></td>
<td></td>
</tr>
<tr><td colspan="4">Printed On: {{ today }} </td></tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<div class="pull-left">
<button class="btn btn-warning" data-pas-print data-print-element-id="printSection"><i class="fa fa-print fa-lg"></i> Print </button>
</div>
<div class="pull-right">
<button class="btn btn-default" data-ng- click="cancel()">Cancel</button>
</div>
the printModel model simply takes the value from the text box and includes it to be printed, just a descriptive term.
I am at a loss as to why this is not working. I did just piece this together from other scripts I found online to work with our application. I am a bit of an angular Newb and I really appreciate any help I can get so thank you in advance. please if you need more information feel free to ask. If I had to guess I would say it has something to do with cloning and the emptying of the element if I had to guess, but I am at a loss as to how to fix it. HELP please.