v-for and computed properties calling methods - javascript-objects

I'm trying to update some properties on a VueJS object list, but I'm having some glitches.
Here's the HTML:
<div id="el">
<p>Total Chats: {{ chats.length }} ({{ unreadCount }} unread)</p>
<button v-on:click="__addChat(true)">Add a Chat</button>
<button v-on:click="__makeAllRead">Read All</button>
<pre>{{ $data | json }}</pre>
<ul>
<li v-for="chat in chats">
<p>
Message {{ chat.id }}
<span v-if="chat.unread"><strong>(UNREAD)</strong></span>
</p>
</li>
</ul>
</div>
And the Vue code:
var vm = new Vue({
el: '#el',
data: {
nextID : 2,
chats: {
'6fc5gh4j3kl_FIRST': {
id : 1,
unread : true,
body : Date(),
}
},
},
methods: {
__addChat: function (unread) {
var chat = {
id : this.nextID++,
unread : unread,
body : Date(),
};
this.chats[this.__makeHash()] = chat;
console.log(this.chats);
},
__makeAllRead : function() {
console.log(Object.keys(this.chats));
for ( var key in Object.keys(this.chats) ) {
// if any tests are invalid
if ( this.chats.hasOwnProperty(key) ) {
this.chats[key] = true;
}
}
},
__countUnread : function() {
var unread = 0;
for ( var key in Object.keys(this.chats) ) {
// if any tests are invalid
if ( this.chats.hasOwnProperty(key) && this.chats[key].unread ) {
unread++;
}
}
return unread;
},
__makeHash: function() {
return '6fc5gh4j3kl1AZ0' + Math.floor((Math.random() * 100) + 1);
},
},
ready: function() {
this.__addChat(false);
},
computed: {
unreadCount: function () {
console.log('counting...');
return this.countUnread();
}
}
});
Here's a Fiddle: http://jsfiddle.net/522aw2n5/7/
Things I cannot understand/fix on this code:
1) A computed property using a method to update the count
2) It displays only the object manually created, not the dynamically ones.
3) I cannot make all messages read by clicking a button.
This is Vue 1.0.0 RC2.
Could you, please, tell me what Am I doing wrong?

Answered on VueJS's Gitter
HTML
<div id="el">
<p>Total Chats: {{ totalChats }} ({{ unreadCount }} unread)</p>
<button v-on:click="__addChat(true)">Add a Chat</button>
<button v-on:click="__makeAllRead">Read All</button>
<pre>{{ $data | json }}</pre>
<ul>
<li v-for="chat in chats">
<p>
{{ chat.id }}
<span v-if="chat.unread"><strong>(UNREAD)</strong></span>
</p>
</li>
</ul>
</div>
Vue Code
var vm = new Vue({
el: '#el',
data: {
nextID : 2,
chats: {
'6fc5gh4j3kl_FIRST': {
id : 1,
unread : true,
body : Date(),
}
},
},
methods: {
__addChat: function (unread) {
var chat = {
id : this.nextID++,
unread : unread,
body : Date(),
};
this.$set('chats.' + this.__makeHash(), chat);
},
__makeAllRead : function() {
console.log(Object.keys(this.chats));
for ( var key in this.chats ) {
// if any tests are invalid
if ( this.chats.hasOwnProperty(key) ) {
this.chats[key].unread = false;
}
}
},
__makeHash: function() {
return 'fc5gh4j3kl1AZ0' + Math.floor((Math.random() * 100) + 1);
},
},
ready: function() {
this.__addChat(false);
},
computed: {
totalChats: function() {
var size = 0, key;
for (key in this.chats) {
if (this.chats.hasOwnProperty(key)) size++;
}
return size;
},
unreadCount: function () {
var unread = 0;
for ( var key in this.chats ) {
// if any tests are invalid
if ( this.chats.hasOwnProperty(key) && this.chats[key].unread ) {
unread++;
}
}
return unread;
}
}
});

Related

How to pass JSON Array {{this.row}} to submit() function to get posted using Axios.post

this.row is Generating form input into JSON Array which I'm trying to post via submit function using Axios but unable to the value please help what's wrong ??
Axios postcode
axios.post('/submit', this.rows).then(response => {
this.rows; //Clear input fields.
this.loaded = true;
Here is my complete code
<template>
<form #submit.prevent="submit">
{{ /* These are 3 buttons which are calling 3 different function to create input boxes */ }}
<div class="d-flex mt-5"><div>
<label>Add A</label>
<button type="button" #click="addRow">01</button>
</div>
<div> <label>Add B</label>
<button type="button" #click="addRow1">02</button>
</div>
<div> <label>Add c</label>
<button type="button" #click="addRow3">03</button>
</div>
</div>
{{ /* this section calls button-counter template from script code */ }}
<div v-for="row in rows" :key="row.id">
<button-counter :name ="row.name" :id="row.id" :value.sync="row.value"></button-counter>
</div>
<div>
<button type="submit" class="btn btn-primary">Add Points</button>
</div>
<div v-if="success" class="alert alert-success mt-3">
Message sent!
</div>
</form>
</template>
<script>
Vue.component("button-counter", {
props: {
value: {
default: "",
}
},
/* This is my template which gets called fro the addition of new inputs ...guess here I need to add v-model so that dynamically generated fields will be posted but I'm unable to get it posted */
template: '<input class="form-control" id= id.row name=row.name type="number" style="margin-top: 10px;" :value="value" #change="$emit(\'update:value\', $event.target.value)">'
});
export default {
props: ['gameId','userId'],
mounted() {
console.log('Component mounted.')
},
data() {
return {
gamex: this.gameId,
rows: [],
count: 0,
fields: {},
errors: {},
success: false,
loaded: true,
};
},
computed: {
total() {
if (this.rows.length) {
return this.rows.reduce((acc, row) => acc += parseInt(row.value), 0);
}
return 0;
}
},
methods: {
addRow: function() {
var txtCount = 1;
let id = "txt_" + txtCount;
this.rows.push({ name:'zero',value:100, description: "textbox1", id });
},
addRow1: function() {
var txtCount = 1;
let id = "txt2_" + txtCount;
this.rows.push({name:'one',value:200, description: "textbox2", id });
},
addRow3: function() {
var txtCount = 1;
let id = "txt3_" + txtCount;
this.rows.push({name:'two',value:300, description: "textbox3", id });
},
submit: function() {
if (this.loaded) {
this.loaded = false;
this.success = false;
this.errors = {};
axios.post('/submit', this.rows).then(response => {
this.rows; //Clear input fields.
this.loaded = true;
this.success = true;
}).catch(error => {
this.loaded = true;
if (error.response.status === 422) {
this.errors = error.response.data.errors || {};
}
});
}
},
followUser() {
axios.post('/chklet/' + this.userId)
.then(response => {
return response.data ;
});
}
},
mounted () {
this.followUser();
}
};
</script>
You can use JSON.stringify(array_to_convert_in_string_to_send_in_ajax) but you will have to json_decode it also in backend server
In server section for example laravel:
$result = json_decode($request->your_array);

How can I make square-connect work with angularjs?

Basing myself on the example provided by the SquareUp documentation (https://github.com/square/connect-api-examples.git). I am trying to integrate squareup to process payments with CC but I do not know what happens.
the view:
<div class="bg-light lter b-b wrapper-md">
<h1 class="m-n font-thin h3"></h1>
</div>
<div class="wrapper-md" >
<div class="row">
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading font-bold">CC info</div>
<div class="panel-body">
<div class="no-boot" ng-controller="PaymentController" ng-cloak>
<div id="successNotification" ng-show="isPaymentSuccess">
Card Charged Succesfully!!
</div>
<form novalidate id="payment-form" ng-hide="isPaymentSuccess">
<div id="card-errors" ng-repeat="error in card_errors">
<li>{{error.message}}</li>
</div>
<div>
<label>Card Number</label>
<div ng-model="data.card.card_number" id="sq-card-number"></div>
</div>
<div>
<label>CVV</label>
<div ng-model="data.card.cvv" id="sq-cvv"></div>
</div>
<div>
<label>Expiration Date</label>
<div ng-model="data.card.expiration_date" id="sq-expiration-date"></div>
</div>
<div>
<label>Postal Code</label>
<div ng-model="data.card.postal_code" id="sq-postal-code"></div>
</div>
<div>
<input ng-click="submitForm()" ng-disabled="isProcessing" type="submit" id="submit" value="Buy Now" class="btn btn-primary">
</div>
</form>
<button id="sq-apple-pay" class="button-apple-pay-block" ng-show="supportApplePay"></button>
</div>
</div>
</div>
</div>
</div>
</div>
the controller:
'use strict';
/* Controllers */
// signin controller
app.controller('PaymentController', ['$scope', '$http', function($scope, $http) {
//for showing #successNotification div
$scope.isPaymentSuccess = false;
//for disabling payment button
$scope.isProcessing = false;
//for disabling apple pay button
$scope.supportApplePay = false;
$scope.data = {
product_id: "001",
user: {},
card: {},
products: {
"001": {
"name": "Paper Origami 1:10,000 scale model (11 inch)",
"value":"1.0",
},
"002": {
"name": "Plastic 1:5000 scale model (22 inch)",
"value":"49.0",
},
"003": {
"name": "Metal & Concrete 1:1000 scale replica (9 feet)",
"value":"5000.0",
}
}
};
$scope.submitForm = function(){
console.log($scope.data)
$scope.isProcessing = true;
$scope.paymentForm.requestCardNonce();
return false
}
var cardNumber = $scope.data.card.card_number = 5409889944179029;
var cvv = $scope.data.card.cvv = 111;
var expirationDate = $scope.data.card.expirationDate = '02/21';
var postalCode = $scope.data.card.postalCode = 3311;
$scope.paymentForm = new SqPaymentForm({
applicationId: 'sandbox-sq0idp-IsHp4BXhhVus21G5JPyYpw',
locationId: 'CBASECJCvmqtoIL1fn3iReEjQRcgAQ',
inputClass: 'sq-input',
inputStyles: [
{
fontSize: '14px',
padding: '7px 12px',
backgroundColor: "transparent"
}
],
cardNumber: {
elementId: 'sq-card-number',
placeholder: '5409889944179029',
value: '5409889944179029'
},
cvv: {
elementId: 'sq-cvv',
placeholder: '111',
value: '111'
},
expirationDate: {
elementId: 'sq-expiration-date',
placeholder: '04/21',
value: '04/21'
},
postalCode: {
elementId: 'sq-postal-code',
placeholder: '33114',
value: '33114'
},
applePay: {
elementId: 'sq-apple-pay'
},
// cardNumber:''+cardNumber,
// cvv:''+cvv,
// expirationDate:''+expirationDate,
// postalCode:''+postalCode,
callbacks: {
cardNonceResponseReceived: function(errors, nonce, cardData) {
if (errors){
$scope.card_errors = errors
$scope.isProcessing = false;
$scope.$apply(); // required since this is not an angular function
}else{
$scope.card_errors = []
$scope.chargeCardWithNonce(nonce);
}
},
unsupportedBrowserDetected: function() {
// Alert the buyer
},
methodsSupported: function (methods) {
console.log(methods);
$scope.supportApplePay = true
$scope.$apply(); // required since this is not an angular function
},
createPaymentRequest: function () {
var product = $scope.data.products[$scope.data.product_id];
return {
requestShippingAddress: true,
currencyCode: "USD",
countryCode: "US",
total: {
label: product["name"],
amount: product["value"],
pending: false,
}
};
},
// Fill in these cases to respond to various events that can occur while a
// buyer is using the payment form.
inputEventReceived: function(inputEvent) {
switch (inputEvent.eventType) {
case 'focusClassAdded':
// Handle as desired
break;
case 'focusClassRemoved':
// Handle as desired
break;
case 'errorClassAdded':
// Handle as desired
break;
case 'errorClassRemoved':
// Handle as desired
break;
case 'cardBrandChanged':
// Handle as desired
break;
case 'postalCodeChanged':
// Handle as desired
break;
}
}
}
});
$scope.chargeCardWithNonce = function(nonce) {
alert("no");
var url = "libs/php_payment/process-card.php";
var data = {
nonce: nonce,
product_id: $scope.data.product_id,
name: $scope.data.user.name,
email: $scope.data.user.email,
street_address_1: $scope.data.user.street_address_1,
street_address_2: $scope.data.user.street_address_2,
city: $scope.data.user.city,
state: $scope.data.user.state,
zip: $scope.data.user.zip
};
$http.post(url, data).success(function(data, status) {
if (data.status == 400){
// display server side card processing errors
$scope.isPaymentSuccess = false;
$scope.card_errors = []
for (var i =0; i < data.errors.length; i++){
$scope.card_errors.push({message: data.errors[i].detail})
}
}else if (data.status == 200) {
$scope.isPaymentSuccess = true;
}
$scope.isProcessing = false;
}).error(function(){
$scope.isPaymentSuccess = false;
$scope.isProcessing = false;
$scope.card_errors = [{message: "Processing error, please try again!"}];
})
}
//build payment form after controller loads
var init = function () {
$scope.paymentForm.build()
};
init();
}]);
error: "Error: [$rootScope:inprog] $digest already in progress
I haven't done angular in a while, but I'm betting that your issue is in:
methodsSupported: function (methods) {
console.log(methods);
$scope.supportApplePay = true
$scope.$apply(); // required since this is not an angular function
},
You are calling $apply() after a non-asyc call, generally you apply new data that you got asynchronously. See Angular Docs

VueJs2:remove item from parent array in component

I have a component with prop List. List is list of input files. At once input changed I add another one input.
Weird behavior if I try to delete .
https://jsfiddle.net/apokjqxx/115/
removeAnother: function(item) {
var vm = this;
var num = vm.$parent.cornerList.indexOf(item);
vm.$parent.cornerList.splice(num, 1);
},
How to reproduce:
choose file in first input
choose file in second input (will added after step 1)
choose file in third input (will added after step 2)
then click to remove on first item in list
Expected: removed first item but has removed last added
Use a key on your list.
<div v-for="(item, index) in list" :key="item.id">
I modified your fiddle to generate an id for each object added to the cornerList array.
var formuploadimage = Vue.extend({
template: '#template-form-upload-image',
props: {
list: {
type: Array
}
},
data: function() {
return {
isFileChanged: false
}
},
watch: {
validCnt: function() {
},
},
methods: {
onFileChange: function(item) {
var vm = this;
let id = Math.max.apply(Math, vm.$parent.cornerList.map(c => c.id)) + 1
var newItem = {id};
vm.$parent.cornerList.push(newItem);
},
removeAnother: function(item) {
var vm = this;
var num = vm.$parent.cornerList.indexOf(item);
vm.$parent.cornerList.splice(num, 1);
},
},
});
var app = new Vue({
el: ".lists-wrappers",
data: {
cornerList: [{id: 1}],
},
components: {
formuploadimage: formuploadimage
},
methods: {
},
});
.select-file{
width:250px;
border:1px solid red;
}
<script src="https://unpkg.com/vue#2.4.4/dist/vue.js"></script>
<div class="lists-wrappers">
<formuploadimage :list="cornerList"></formuploadimage>
</div>
<script type="text/x-template" id="template-form-upload-image">
<div>
<div v-for="(item, index) in list" :key="item.id">
<div class="select-file">
REMOVE<br/>
<label for="file-input">
+Add photo
</label>
<input type="file" #change="onFileChange(item)" />
</div>
</div>
</div>
</script>

Occasional AngularJS error when directive is compiling

I have an AngularJS directive that renders into a custom social share widget. Out of about 10,000 page views per day, around 1 or 2 of those times, Angular errors out after starting to compile the directive. This leaves the raw HTML partial in the DOM, visible to the user.
I only came to know of this error because it was reported by several users. I can't reproduce it, but I have devised some informative logging which shows that it is occurring.
Each time this has occurred:
Browser is always Chrome
OS is Mac or Windows
Angular starts the compile phase, but fails before starting post link
Angular reports an error during the compile phase, but the 'exception' object passed to the '$exceptionHandler' service is always null.
No other JavaScript errors are reported
This error is occurring for some of the same IPs across multiple days.
Has anyone out there had a similar issue?
Edit
Here's my code...
JavaScript:
(function () {
angular.module('common', []);
angular.module('common')
.filter('encodeURIComponent', function () {
return window.encodeURIComponent;
});
function configure($provide) {
// Pass all Angular errors to Loggly
$provide.decorator("$exceptionHandler", function ($delegate) {
return function exceptionHandlerDecorator(exception, cause) {
$delegate(exception, cause);
_LTracker.push({
'error': 'angularError',
'app': 'shareCounts',
'err': exception,
'element': cause
});
};
});
}
angular.module('common')
.config(['$provide', configure]);
function configure($provide) {
// Defines available share options as well as behaviors of the share popup windows
function shareLinksConfig() {
return {
'facebook': {
width: 670,
height: 200,
urlBase: 'https://www.facebook.com/sharer/sharer.php?',
shareParamPre: 'u=',
msgParamPre: '',
mediaParamPre: '',
addParams: ''
},
'twitter': {
width: 550,
height: 420,
urlBase: 'https://twitter.com/intent/tweet?',
shareParamPre: 'url=',
msgParamPre: '&text=',
mediaParamPre: ''
},
'googlePlus': {
width: 600,
height: 600,
urlBase: 'https://plus.google.com/share?',
shareParamPre: 'url=',
msgParamPre: '',
mediaParamPre: '',
addParams: ''
},
'linkedIn': {
width: 600,
height: 400,
urlBase: 'http://www.linkedin.com/shareArticle?',
shareParamPre: 'url=',
msgParamPre: '',
mediaParamPre: '',
addParams: '&mini=true'
},
'pinterest': {
width: 750,
height: 320,
urlBase: 'https://www.pinterest.com/pin/create/button/?',
shareParamPre: 'url=',
msgParamPre: '&description=',
mediaParamPre: '&media=',
addParams: ''
},
'email': {
width: 0,
height: 0,
urlBase: '',
shareParamPre: '',
msgParamPre: '',
mediaParamPre: '',
addParams: ''
}
};
}
$provide.factory('shareLinksConfig', shareLinksConfig);
}
angular.module('common')
.config(['$provide', configure]);
function ShareLinksController($scope, shareLinksService) {
sendToLoggly.push("A \"ShareLinksController\" started constructing...");
sendToLoggly.push("...and the $scope is typeof...");
sendToLoggly.push(typeof $scope);
var vm = this;
vm.share = function ($event, shareVia) {
if (shareVia !== 'email') {
$event.preventDefault();
// console.log($scope.mediaUrl);
shareLinksService.openPopUp(shareVia, $scope.shareUrl, $scope.shareMsg, $scope.mediaUrl);
}
// Tell Google Analytics share link was clicked
shareLinksService.pushGAEvent($scope.analyticsLocation, shareVia, $scope.shareUrl);
};
$scope.shareLinksShown = true; // Initialized to true, but then this gets set to false in the directive's link function if slideIn is true
vm.toggle = function ($event) {
$event.preventDefault();
$scope.shareLinksShown = !$scope.shareLinksShown;
};
sendToLoggly.push("...and controller finished constructing.");
}
angular.module('common')
.controller('ShareLinksController', ["$scope", "shareLinksService",
ShareLinksController]);
function fuShareLinks($http, shareLinksConfig, testRenderingService) {
function compile() {
sendToLoggly.push("A \"fuShareLinks\" directive started compiling...");
testRenderingService.testShareCounts();
return function postLink(scope) {
sendToLoggly.push("A \"fuShareLinks\" directive started postLinking...");
function Settings(shareVia, slideInDir, slideToggleLabel, colorized, showCounts) {
var self = this,
prop,
splitArray;
/* --------
ShareVia
--------
Comma separated list of ways to share
Accepted options are: 'facebook, twitter, googlePlus, linkedIn, pinterest, email' */
// Copy the properties from the config and initialize to false
self.shareVia = {};
for (prop in shareLinksConfig) {
if (shareLinksConfig.hasOwnProperty(prop)) {
self.shareVia[prop] = false;
}
}
if (typeof shareVia === 'string') {
splitArray = shareVia.split(',');
} else {
splitArray = [];
}
// Check each value of splitArray, if it is in possible share options,
// set that option to true.
angular.forEach(splitArray, function (value) {
// Clean up 'value' a bit by removing spaces
value = value.trim();
if (value.length > 0) {
if (self.shareVia.hasOwnProperty(value)) {
self.shareVia[value] = true;
}
}
});
/* --------
Slide In
--------
The slide-in functionality is activated by passing a value to 'slideInDir'.
Accepted values are 'left' or 'down' (case insensitive)
The 'slideToggleLabel' can be any string, if empty, it defaults to 'Share'. */
self.slideIn = {
direction: '',
label: 'Share'
};
if (typeof slideInDir === 'string') {
slideInDir = slideInDir.toUpperCase();
}
switch (slideInDir) {
case 'LEFT':
self.slideIn.direction = 'left';
break;
case 'DOWN':
self.slideIn.direction = 'down';
break;
}
if (typeof slideToggleLabel === 'string') {
self.slideIn.label = slideToggleLabel;
}
/* ---------
Colorized
---------
'true', 'yes', or 'colorized' (case insensitive) -- results in true
defaults to false */
self.colorized = false;
if (typeof colorized === 'string') {
colorized = colorized.toUpperCase();
}
switch (colorized) {
case 'TRUE':
self.colorized = true;
break;
case 'YES':
self.colorized = true;
break;
case 'COLORIZED':
self.colorized = true;
break;
}
/* -----------
Show Counts
-----------
'true', 'yes', or 'show' (case insensitive) -- results in true
defaults to false */
self.showCounts = false;
if (typeof showCounts === 'string') {
showCounts = showCounts.toUpperCase();
}
switch (showCounts) {
case 'TRUE':
self.showCounts = true;
break;
case 'YES':
self.showCounts = true;
break;
case 'SHOW':
self.showCounts = true;
break;
}
}
scope.settings = new Settings(
scope.shareVia,
scope.slideInDir,
scope.slideToggleLabel,
scope.colorized,
scope.showCounts
);
// Initally hide the share links, if they are set to toggle
if (scope.settings.slideIn.direction !== '') {
scope.shareLinksShown = false;
}
function ShareCounts(shareVia) {
var self = this;
angular.forEach(shareVia, function (value, name) {
self[name] = 0;
});
$http.get(
'/local/social-share-counts/?url=' +
encodeURIComponent(scope.shareUrl)
).success(function (data) {
/* Check for share counts in the returned data.
Must use consistent naming for the social networks
from shareLinksConfig properties all the way to the
JSON data containting the counts.
Expected JSON format:
{
"twitter": {
"count": 42,
"updated": "2015-03-25T15:13:48.355422"
},
"facebook": {
"count": 120,
"updated": "2015-03-25T15:13:47.470778"
}
}
*/
angular.forEach(shareVia, function (value, name) {
if (data[name] && data[name]["count"]) {
self[name] = data[name]["count"];
}
});
}).error(function (data, status) {
sendToLoggly.push("HTTP Response " + status);
});
}
// If showing share counts, get the counts from the specified networks
if (scope.settings.showCounts) {
scope.shareCounts = new ShareCounts(scope.settings.shareVia);
}
sendToLoggly.push("...and directive finished postLinking.");
};
sendToLoggly.push("...and directive finished compiling.");
}
return {
restrict: 'E',
scope: {
shareVia: '#',
shareUrl: '#',
shareMsg: '#',
mediaUrl: '#',
analyticsLocation: '#',
slideInDir: '#',
slideToggleLabel: '#',
colorized: '#',
showCounts: '#'
},
controller: 'ShareLinksController',
controllerAs: 'shrLnksCtrl',
templateUrl: '/angular-partials/common.share-links.html',
compile: compile
};
}
angular.module('common')
.directive('fuShareLinks', ['$http', 'shareLinksConfig', 'testRenderingService', fuShareLinks])
.factory('testRenderingService', function () {
var timerId = null;
function evalShareRender() {
var renderError = (-1 < $('em.ng-binding')
.text()
.indexOf('{{'));
if (renderError) {
console.error('RENDER ERROR');
_LTracker.push({
'error': 'rendering',
'app': 'shareCounts',
'statusMsgs': sendToLoggly,
'userAgent': navigator.userAgent
});
}
}
return {
testShareCounts: function () {
if (!timerId) {
timerId = window.setTimeout(evalShareRender, 5000);
}
}
};
});
function shareLinksService(shareLinksConfig) {
function openPopUp(shareVia, shareUrl, shareMsg, mediaUrl) {
var width,
height,
urlBase,
shareParamPre,
msgParamPre,
mediaParamPre,
addParams,
popUpUrl;
width = shareLinksConfig[shareVia].width;
height = shareLinksConfig[shareVia].height;
urlBase = shareLinksConfig[shareVia].urlBase;
shareParamPre = shareLinksConfig[shareVia].shareParamPre;
msgParamPre = shareLinksConfig[shareVia].msgParamPre;
mediaParamPre = shareLinksConfig[shareVia].mediaParamPre;
addParams = shareLinksConfig[shareVia].addParams;
popUpUrl = encodeURI(urlBase);
popUpUrl += encodeURI(shareParamPre);
popUpUrl += encodeURIComponent(shareUrl);
if (msgParamPre && shareMsg) {
popUpUrl += encodeURI(msgParamPre);
popUpUrl += encodeURIComponent(shareMsg);
}
if (mediaParamPre && mediaUrl) {
popUpUrl += encodeURI(mediaParamPre);
popUpUrl += encodeURIComponent(mediaUrl);
}
popUpUrl += encodeURI(addParams);
// Open the social share window
window.open(popUpUrl, '_blank', 'width=' + width + ',height=' + height);
}
function pushGAEvent(analyticsLocation, shareVia, shareUrl) {
function capitalize(firstLetter) {
return firstLetter.toUpperCase();
}
var gaEventAction = shareVia;
gaEventAction = gaEventAction.replace(/^[a-z]/, capitalize);
gaEventAction += ' - Clicked';
_gaq.push([
'_trackEvent',
analyticsLocation + ' - SocialShare',
gaEventAction,
shareUrl
]);
}
return {
openPopUp: openPopUp,
pushGAEvent: pushGAEvent
};
}
angular.module('common')
.factory('shareLinksService', ['shareLinksConfig', shareLinksService]);
}());
HTML:
<div class="share-links-wrapper" ng-class="{ 'right': settings.slideIn.direction === 'left', 'center': settings.slideIn.direction === 'down' }" ng-cloak>
<a href="#" class="toggle" ng-show="settings.slideIn.direction != ''" ng-click="shrLnksCtrl.toggle($event)">
<i class="fuicon-share"></i>{{ settings.slideIn.label }}
</a>
<div class="share-links" ng-class="{ 'share-links-colorized': settings.colorized }" ng-show="shareLinksShown">
<ul>
<li ng-show="settings.shareVia.facebook">
<a href="#" ng-click="shrLnksCtrl.share($event, 'facebook')"
class="fuicon-hex-facebook">
</a>
<em ng-show="settings.showCounts && shareCounts.facebook > 0">
{{ shareCounts.facebook }}
</em>
</li>
<li ng-show="settings.shareVia.twitter">
<a href="#" ng-click="shrLnksCtrl.share($event, 'twitter')"
class="fuicon-hex-twitter">
</a>
<em ng-show="settings.showCounts && shareCounts.twitter > 0">
{{ shareCounts.twitter }}
</em>
</li>
<li ng-show="settings.shareVia.googlePlus">
<a href="#" ng-click="shrLnksCtrl.share($event, 'googlePlus')"
class="fuicon-hex-googleplus">
</a>
<em ng-show="settings.showCounts && shareCounts.googlePlus > 0">
{{ shareCounts.googlePlus }}
</em>
</li>
<li ng-show="settings.shareVia.linkedIn">
<a href="#" ng-click="shrLnksCtrl.share($event, 'linkedIn')"
class="fuicon-hex-linkedin">
</a>
<em ng-show="settings.showCounts && shareCounts.linkedIn > 0">
{{ shareCounts.linkedIn }}
</em>
</li>
<li ng-show="settings.shareVia.pinterest && mediaUrl">
<a href="#" ng-click="shrLnksCtrl.share($event, 'pinterest')"
class="fuicon-hex-pinterest">
</a>
<em ng-show="settings.showCounts && shareCounts.pinterest > 0">
{{ shareCounts.pinterest }}
</em>
</li>
<li ng-show="settings.shareVia.email">
<a href="mailto:?subject={{ shareMsg | encodeURIComponent }}
&body={{ shareUrl | encodeURIComponent }}"
ng-click="shrLnksCtrl.share($event, 'email')"
class="fuicon-hex-email">
</a>
</li>
</ul>
</div>
</div>
Not had such an issue, but as its so infrequent could you make it reload the page?
Also, do you know about ng-cloak? it can be useful to hide the raw stuff :)
Could it be a race condition?

how can i update the template view or json data so that i could re-render my template view in backbone.js

i want to update the view, as i click on follow button, id for follow button is btn-follow.
i want to update the ui if template, that i when i click on follow button, if value in console data is true follow button should change in "FOLLOW" if value in console is false then button caption should be UN-FOLLOW. how can i update the view or how can i update the joson data and re-render the template.
my view code is here.
spine.module("communityApp", function (communityApp, App, Backbone, Marionette, $, _) {
// Load template
var pforumTemplateHtml = App.renderTemplate("pforumTemplate", {}, "communityModule/tabContainer/pforum");
// Define view(s)
communityApp.Views.pforumView = Marionette.ItemView.extend({
template: Handlebars.compile($(pforumTemplateHtml).html()),
tagName: "li",
onRender: function () {
this.object = this.model.toJSON();
},
events: {
"click .btn-comment" : "showComments",
"click #recent-btn": "recent",
"click #my-posts": "myposts",
"click #popular-btn": "popular",
"click #follow-btn": "follow",
"click #my-posts": "LeftLinks",
"click #popular-btn": "LeftLinks",
"click .btn-follow": "activityBtn",
"click #like-btn" : "activityBtn",
"click #post-comments-btn": "showCommentEiditor"
},
postcomments : function ()
{
$("#recent-post-main-container").hide();
$("#recent-post-main-container2").show();
},
showCommentEiditor : function (){
$(".comment-popup-container").show();
$(".comment-txt-area").val('');
},
showPforumTab : function ()
{
$("#recent-post-main-container2").show();
$("#recent-post-main-container").hide();
},
showComments : function(){
$("#loading").show();
$(".tab-pane").hide();
$(".left-content").hide();
$("#recent-post-main-container2").show();
$(".left-content-commentEditor").show();
//$(".comm-tab-content-container").css('height','200px');
$(".comment-txt-area").val('');
$(".left-content-comment").show();
},
hideCommentPopup : function ()
{
$("#public-question-comment").hide();
},
// Show Loading sign
showLoading : function () {
$('#loading').show();
},
// UnLoading Function
hideLoading : function (){
$('#loading').hide();
},
// Add New Event Function
addEvent : function()
{
//$("#name").val(getBackResponse.user.FullName);
//$("#phone").val(getBackResponse.user.CellPhone);
//$("#email").val(getBackResponse.user.UserName);
$(".overly.addevent").show();
$('#lang').val(lat);
$('#long').val(long);
document.getElementById("my-gllpMap").style.width = "100%";
var my_gllpMap = document.getElementById("my-gllpMap");
google.maps.event.trigger( my_gllpMap, "resize" );
},
setValues : function(key,value)
{
window.localStorage.setItem(key,value);
},
getValues : function (key)
{
return window.localStorage.getItem(key);
},
closeAddEvent:function ()
{
$(".overly.addevent").hide();
},
// Show Over lay
showOverly:function ()
{
$('.overly-right-tab').show();
},
// Hide Loading sign
hideOverly : function()
{
$('.overly-right-tab').hide();
},
enlargeImage : function ()
{
$('#image').css('width','212px');
$('#image').css('height','150px');
},
activityBtn: function (e) {
var elem = $(e.target);
if (elem.hasClass('inactive')) {
return false;
}
var activity = elem.attr('name');
switch (activity) {
case "like-Button":
var _this = $.extend({},this,true);
_this.activity = 'like-Button';
this.activityBtnSubmit.call(_this);
break;
//
case "follow-button":
var _this = $.extend({},this,true);
_this.activity = 'follow-button';
this.activityBtnSubmit.call(_this);
break;
}
},
//For Like Post
activityBtnSubmit: function (modalThis) {
// var o = (this.parentThis) ? this.parentThis.object : this.object;
//var o = "52fa2ccc9bca9ac90c000051";
var func = _.bind(function () {
//var hmObj = new MessageApp.Controllers.hmAlertsController();
//hmObj.init();
}, this);
switch (this.activity) {
case "like-Button":
App.ids = null;
App.ids2 = null;
App.ids = this.object.id;
App.ids2 = this.object.iLiked;
if(App.ids2 === true) {
App.action = 0;
}
else if(App.ids2 === false) {
App.action = 1;
}
var data = {
id: this.object.id,
iLiked:App.action,
sessionToken:loginUser.sessionToken,
};
$.when(App.request('alertActivity:entities', {
origin: 'pforum',
id: this.object.id,
iLiked:(App.action),
sessionToken:loginUser.sessionToken,
//value : value,
dataToSend: JSON.stringify(data),
activity:this.activity,
}))
.then(func);
App.ids1 = (data.id);
break;
case "follow-button":
App.ids = null;
App.ids2 = null;
App.ids = this.object.UserId;
App.ids2 = this.object.iFollow;
if(App.ids2 === true) {
// $(".btn-follow").html("UN-FOLLOW");
App.action = 0;
}
else if(App.ids2 === false) {
//$(".btn-follow").html("FOLLOW");
App.action = 1;
}
if (App.ids) {
alert (App.ids);
$(".btn-follow").html("UN-FOLLOW");
//App.action = 0;
}
else
{
$(".btn-follow").html("FOLLOW");
//App.action = 1;
}
var data = {
id: this.object.UserId,
iFollow:App.action,
sessionToken:loginUser.sessionToken,
};
$.when(App.request('alertActivity:entities', {
origin: 'pforum',
id: this.object.UserId,
iFollow:(App.action),
sessionToken:loginUser.sessionToken,
//value : value,
dataToSend: JSON.stringify(data),
activity:this.activity,
}))
.then(func);
App.ids1 = (data.UserId);
break;
}
return true;
}
});
var RowView = Backbone.View.extend({
events: {
"click .btn-follow": function() {console.log(this.model.get("name"));}
},
initialize: function(){
this.model.on('change', this.render, this);
},
render: function() {
var html=_.template(rowTemplate,this.model.toJSON());
this.setElement( $(html) );
return this;
},
});
// define collection views to hold many communityAppView:
communityApp.CollectionViews.pforumCollectionViews = Marionette.CollectionView.extend({
tagName: "ul",
itemView: communityApp.Views.pforumView
});
});
my template code is here.
<div>
<div class="comm-tab-row">
<div class="post-left-panel">
<div class="post-image-container">
<img src="{{UserImageURL}}" alt="" class="post-image" /></br>
{{#if iLiked}}
<img src="images/myCommunity/liked#2x.png" width="20" height="19" id="like-btn" name = "like-Button" >
{{else}}
<img src="images/myCommunity/like#2x.png" width="20" height="19" id="like-btn" name = "like-Button" >
{{/if}}
({{NumLikes}})
</div>
</div>
<div class="post-body">
<h5 class="comm-tab-heading">
<span class="navigate-screen" id="{{Id}}" style="text-decoration:underline;">
{{UserName}}
</span>
<span>
-
</span>
<span>
{{format_date Time ""}}
</span>
</h5>
{{Message}}
</div>
<div class="comm-right-panel">
{{#if iFollow}}
UN-FOLLOW
{{else}}
FOLLOW
{{/if}}
{{NumComments}} - COMMENT
</div>
</div>
You can add a new boolean to the model of your view isFollowing. You can then add a condition inside your template to determine which button to render.
<% if(isFollowing){ %>
<button> Unfollow </button>
<% } else { %>
<button> Follow</button>
<% } %>
To rerender the view call the render function from your event handler.
events: {
"click .btn-follow": function() {
//Do comething useful..
this.render();
}
},

Resources