Still building off of this question, to pull in media data from the tweet JSON that I've made a call to. At first, I thought it would be as simple as iterating through the JSON, but the entities.media.media_url are not always present, and will return undefined errors for the tweets that don't contain them. I tried creating a method that would pull the data if it exists, but I'm not able to get it to iterate.
tweets.component.html
<div class="tweet-container">
<div *ngFor="let item of tweetsdata" class="tweets-card">
<div class="tweet-text">
<p class="tweet-date">{{item.created_at | slice:0:10}}</p>
<p>{{item.text}}</p>
<!-- <img src={{getImage()}}> -->
<!-- <p>hello: {{item.entities?.media[0].media_url}}</p> -->
<p>{{getImage()}}</p>
<div class="interact-tweet">
<i class="fa fa-reply" aria-hidden="true"></i>
<i class="fa fa-retweet" aria-hidden="true"></i>
<i class="fa fa-heart" aria-hidden="true"></i>
</div>
</div>
</div>
</div>
tweets.component.ts
...
searchcall() {
const headers = new Headers();
// const searchterm = 'query=' + this.searchquery;
const searchterm = 'query=from%3Adailymuse%20%23' + this.searchquery;
headers.append('Content-Type', 'application/X-www-form-urlencoded');
this.http.post('https://localhost:3000/search', searchterm, {headers: headers}).subscribe((res) => {
this.tweetsdata = [
res.json().data.statuses[0],
res.json().data.statuses[1],
res.json().data.statuses[2],
res.json().data.statuses[3],
res.json().data.statuses[4]
];
console.log(this.tweetsdata);
this.screen_name = this.tweetsdata[0].user.screen_name;
this.user = this.tweetsdata[0].user.name;
this.profile_img_url = this.tweetsdata[0].user.profile_image_url_https;
this.user_id = this.tweetsdata[0].user.id_str;
});
}
getImage() {
if (this.tweetsdata.entities) // will keep returning undefined because it's not pointing to a specific tweet in the array, tweetsdata
{
const imgURL = this.tweetsdata.entities.media[0].media_url;
console.log(imgURL);
return imgURL;
} else {
console.log('nope');
}
}
I think *ngIf would make the most sense to use, but I'm unsure how to set up the statement to check if the key exists first, then present the link. This is what I've tried:
<p *ngIf="item.entities">{{item.entities.media[0].media_url}}</p>
Which technically works if there is an attached image present, but it breaks the code for the following tweets that don't contain an image. Am I setting up the if statement correctly?
Related
Currently a favorites function I have created with Vanilla JS works by storing the selected objects in local storage. But, when an object is removed, and then a new item is added to that same favorites array, both the original (removed) object and the newly added favorite show up in the viewport. I can confirm that both objects are removed from the array providing the data for the favorites section and then both show up when only one new object is added, but I do not know why this issue is occurring.
I have made sure to check that there is no overlap between my arrays. I print all objects that are added to the DOM into local storage for access with the favorites function and later cart functions. Included is the code for a favorites section-
Created item from original array object below-
function feetCard(array){
document.getElementById('mainpageSectionforJS').innerHTML = "";
let footCard = document.querySelector('#mainpageSectionforJS');
console.log(array,"array name");
localStorage.setItem("feetarray", JSON.stringify(array));
console.log(array, "array name");
let data = JSON.parse(localStorage.getItem("feetarray"));
console.log(data, "item data");
data.forEach(component => {
localStorage.setItem(component.valAssign, JSON.stringify(component))
});
data.forEach(component => {
footCard.innerHTML = footCard.innerHTML +
`<div class="card card-margin" id="${component.valAssign}">
<div class="card-header">
<h4> ${component.name} </h4>
<a class="kneeClick btn btn-primary" onclick="footFavorites(${component.valAssign})" > Add To Favorites </a>
<div class="card-body">
<img class="card-image" src="${component.image}"></img>
<h5> Product Description </h5>
<div>${component.manufacturer}</div>
<div>${component.lcode1}</div>
<div>${component.lcode2}</div>
<div>${component.lcode3}</div>
<div>${component.lcode4}</div>
<div>${component.hdcode}</div>
<div>$${component.cost}</div>
<div>${component.reimbursement}</div>
<div>${component.percent}</div>
<div>${component.pdac}</div>
<a class="btn btn-primary" href="${component.link}" target="_blank">${component.linkname}</a>
<input type="button" class="additionSelectButton"></input>
</div>
</div>
</div>`;
console.log("Created", component.card, "Cards");
});
console.log("Card Creation Complete");
};
Next, after clicking the favorites button-
footFavoritesArray = [];
function footFavorites(foot){
console.log(foot, "foot object");
console.log(foot.id, "foot id object");
let getStoredFavorite = JSON.parse(localStorage.getItem(foot.id));
console.log(getStoredFavorite, "retrieved cart item from local storage");
// retrieve the stored favorite item
footFavoritesArray.push(getStoredFavorite);
console.log(footFavoritesArray, "local storage array with favorite item");
// add the item to the cart array
localStorage.setItem("Foot Favorites", JSON.stringify(footFavoritesArray))
// push the cartArray to local storage
let getFavorites = JSON.parse(localStorage.getItem("Foot Favorites"));
console.log(getFavorites, "local storage favorite array");
// retrieve the stored array to check the values
document.getElementById('footItemSectionJS').innerHTML = "";
// clear the favorites viewport so the older items are removed, and redisplayed as a new one is added
let favoritesLocation = document.querySelector('#footItemSectionJS');
// document.getElementById('footItemSectionJS').innerHTML = getFavorites;
// set the location where the favorite should show in the new configuration
getFavorites.forEach(component => {
favoritesLocation.innerHTML = favoritesLocation.innerHTML +
`<div class="card favorites card-margin" id="${component.valAssign}">
<a class="footClick btn-small btn btn-primary" onclick="footCartItem(${component.valAssign})" > + Cart </a>
<img class="card-image" src="${component.image}"></img>
<div class="card-header">
<h4 id=""> ${component.name} </h4>
<a class="footClick btn btn-primary" onclick="removeFavorites(${component.valAssign})" > Remove Favorite </a>
<div id="">HD Code: ${component.hdcode}</div>
<h5><u> L-Codes </u></h5>
<div class="lcodes">
<div id="${component.lcode1}">${component.lcode1}</div>
<div id="${component.lcode2}">${component.lcode2}</div>
<div id="${component.lcode3}">${component.lcode3}</div>
<div id="${component.lcode4}">${component.lcode4}</div>
<div id="${component.lcode5}">${component.lcode5}</div>
<div id="${component.lcode6}">${component.lcode6}</div>
</div>
</div>
</div>
</div>`;
console.log("Created", component.card, "Cards");
});
}
Then, remove that favorite-
function removeFavorites(item){
console.log(item[0].id, "item [0].id");
let getfavorite = JSON.parse(localStorage.getItem("Favorites"));
console.log(getfavorite, "local storage favorite array");
// the favorites array to be modified
let favoriteSpread = {...getfavorite};
console.log(favoriteSpread, "favoriteSpread");
let parts = JSON.parse(localStorage.getItem(item[0].id));
console.log(parts, "parts, the item created from the array item in local storage ");
let indexItem = getfavorite.map(object => object.valAssign).indexOf(item[0].id);
console.log(indexItem, "Index Item")
getfavorite.splice(indexItem, 1);
console.log(getfavorite, "getfavorite Array spliced")
// splice out the item from the favorite array.
localStorage.setItem("Favorites", JSON.stringify(getfavorite));
// push the modified favoriteArray back to local storage
let showfavorite = JSON.parse(localStorage.getItem("Favorites"));
console.log(showfavorite, "local storage favorite array");
// retrieve the favorite array back from local storage
document.getElementById('footItemSectionJS').innerHTML = "";
// clear the favorites viewport so the older items are removed, and redisplayed as a new one is added
let favoritesLocation = document.querySelector('#footItemSectionJS');
// document.getElementById('footItemSectionJS').innerHTML = getFavorites;
// set the location where the favorite should show in the new configuration
showfavorite.forEach(component => {
favoritesLocation.innerHTML = favoritesLocation.innerHTML +
`<div class="card card-margin" id="${component.valAssign}">
<a class="kneeClick btn-small btn btn-primary" onclick="cart(${component.valAssign})" > + Cart </a>
<img class="card-image" src="${component.image}"></img>
<div class="card-header">
<h4 id=""> ${component.name} </h4>
<a class="kneeClick btn btn-primary" onclick="removeFavorites(${component.valAssign})" > Remove Favorite </a>
<div id="">HD Code: ${component.hdcode}</div>
</div>
</div>
</div>`;
console.log("Created", component.card, "Cards");
});
// display the retrieved array items in the "favorite"
// reload the favorite and display it anew
}
last, here is a snapshot of what is occurring in my local storage-
First, saved favorite-
[
{
"valAssign": "abc",
"manufacturer": "abc",
"name": "abc",
}
]
Second, removed-
[]
Third, add favorite of another item-
[
{
"valAssign": "abc",
"manufacturer": "abc",
"name": "abc",
},
{
"valAssign": "def",
"manufacturer": "def",
"name": "def",
}
]
also, in my local storage, the Value of the key/value pair looks like [,...] where other times it will be an object showing up in that line. Trying to provide as much information as possible.
Thanks for your help, this has stumped me.
as Layhout above answered for me, it was an issue of scope. I was not modifying the global array, only the locally stored one. That means that whenever I added a new item to the array I also added any globally stored array objects to local storage and those showed up on my viewport. Where I differed in his fix, which took me down the right path, is I am keeping the global array global, but modifying it with the function to remove a favorite. As follows-
footFavoritesArray = [];
function footFavorites(foot){
HERE IS THE ADDING FAVORITES FUNCTION (you can see the code above in the
intial post)
});
footFavoritesArray = getFavorites;
console.log(footFavoritesArray, "This is the modified global foot favorite
array")
// change the global value of the array above
// Above is the code to change the global array through the function,
notice the closing bracket is below this text.
}
function removeFootFavorites(item){
THIS IS THE LOCATION OF THE REMOVE FAVORITE CODE
});
footFavoritesArray = showfavorite;
console.log(footFavoritesArray, "This is the modified global foot favorite
array")
// change the global value of the array above
// Above is the most important code, to change the global array to the value
established by local storage.
}
I'm having this sanitize URL error in Angular, I've seen many solutions, but I've not been able to use them in my scenario, that's why I'm asking the question.
Here is my function:
#Input()
maxFileSize: number = 1000000;
public fileChangeEvent(fileInput: any) {
if (fileInput.target.files && fileInput.target.files[0]) {
const reader = new FileReader();
reader.onload = (e: any) => {
if (e.target.result) {
if (e.target.result.length < this.maxFileSize) {
this.value = e.target.result;
} else {
alert(`Logo size ${e.target.result.length} cannot exceed ${this.maxFileSize} bytes.`);
}
}
};
reader.readAsDataURL(fileInput.target.files[0]);
}
}
I've tried this.sanitizer.bypassSecurityTrustUrl(url), but in my case, fileInput.target.files[0] is a blob, so I always get an error when wrapping it worth the sanitizer function.
I'm using it in the view like this:
<ng-container *ngIf="value">
<div class="input-group-append">
<div class="img-thumbnail">
<img src="{{value}}" alt="Preview" />
</div>
<button class="btn btn-danger btn-lg" type="button" (click)="clearLogo()">
<i class="fa fa-trash" aria-hidden="true"></i>
Delete
</button>
</div>
</ng-container>
enter code here
I've also tried [src]="{{value}}", but that did not work as well.
I'm getting this error:
WARNING: sanitizing unsafe URL value
Please where am I getting it wrong?
I hope this fixes your issue.
constructor(private sanitizer:DomSanitizer){...}
....
let file = event.target.files[0];
let blob = new Blob([file], { type: file.type });
let url = window.URL.createObjectURL(blob);
this.value = this.sanitizer.bypassSecurityTrustUrl(url);
Im trying to achieve this piece of code but in my console it says thing is null which is weird because when I look in the console, sessionStorage isn't empty...
$(".btn-alert").click(function(){
var identifierOfSpan = $(this > "span").text();
for(var prop in sessionStorage){
var thing = JSON.parse(sessionStorage.getItem(prop))
if(thing.id == identifierOfSpan){
sessionStorage.removeItem(prop);
}
}
$(this).closest(".voyages").remove();
if(sessionStorage.length == 0){
alert("Message!");
location.href="reservation.html"
}
});
the button is supposed to delete the div and the sessionStorage item which looks like this
Html :
<div class="voyages">
<button class="btn btn-alert btn-md mr-2" tabindex="-1">delete the flight</button>
<span>ID : 4224762</span>
<div class="infos">
<img src="img/angleterre.jpg" alt="maroc">
<div>
<ul>
<li><h5>Angleterre, Londres (LON)</h5></li>
<li><h5>2 adulte(s)</h5></li>
<li><h5> Aucun enfants </h5></li>
<li><h5>Type : Couple</h5></li>
</ul>
</div>
</div>
<hr>
<h3>Options</h3>
<ul>
<li>voiture : 0</li>
<li>Hotel : 0 </li>
</ul>
<hr>
<h3>Prix :3713$</h3>
If I'm reading your question correctly, you want to...
Click on a button
Find the first sibling <span> element and parse a number out of its text content
Remove all sessionStorage items (JSON serialized objects) with matching id properties
For the ID, I highly recommend adding some data directly to the <button> to help you identify the right record. If you can, try something like
<button class="btn btn-alert btn-md mr-2" data-voyage="4224762"...
Try something like this
$('.btn-alert').on('click', function() {
const btn = $(this)
const id = btn.data('voyage')
// or, if you cannot add the "data-voyage" attribute
const id = btn.next('span').text().match(/\d+$/)[0]
// for index-based removal, start at the end and work backwards
for (let i = sessionStorage.length -1; i >= 0; i--) {
let key = sessionStorage.key(i)
let thing = JSON.parse(sessionStorage.getItem(key))
if (thing.id == id) {
sessionStorage.removeItem(key)
}
}
// and the rest of your code
btn.closest(".voyages").remove();
if(sessionStorage.length === 0) {
alert("Message!");
location.href = 'reservation.html'
}
})
The problem with using a for..in loop on sessionStorage is that you not only get any item keys added but also
length
key
getItem
setItem
removeItem
clear
I have no clue how to even begin explaining this situation but I'll try my best. I have a simple Spanish-English-Spanish dictionary lookup page with a text box, a Lookup button, and a div to show the results. When you enter a word to lookup in the text box and hit Lookup, the results are shown in the div below.
In the results some words are hyperlinked so when you click on them, you get the search result for the clicked word in the div. That's just like any online dictionary service functions. It works perfect except that the second functionality doesn't seem to work on the first click after a typed search. For example:
You type pedir in the input box and hit Lookup. The div below now shows the detailed meaning of pedir including hyperlinked words like ask, English for pedir. Now, you click ask which should refresh the div and show you the Spanish meanings of ask including words like pedir. However, it just refreshes the div and shows the same content as if you looked up pedir a second time. But when you click on ask a second time now, it works fine as expected. It must be noted that the words are hyperlinked appropriately and there's no mis-linking going on here. Not only that, other links (such as the ones on the navigation tab on top) also don't seem to work on first click. This happens every time a new word is looked up.
Hope the above example illustrates the problem well enough; at least that's what I have tried. My routing and controllers look like this:
var asApp = angular.module('asApp', ['ngRoute']);
asApp.config(function($routeProvider) {
$routeProvider
.when('/', {
title: 'Home of thesite – Radical Spanish learning tips and tricks for the adventurous learner',
templateUrl : 'pages/home.html',
controller : 'mainController'
})
// route for dictionary
.when('/dictionary', {
title: 'The dictionary',
templateUrl : 'pages/dictionary.html',
controller : 'mainController'
})
// route for dictionary term
.when('/dictionary/:word2lookup', {
title: 'The thesite dictionary',
templateUrl : 'pages/dictionary.html',
controller : 'dictController'
})
// route otherwise
.otherwise({
title: 'thesite – Radical Spanish learning tips and tricks for the adventurous learner',
templateUrl : 'pages/home.html',
controller : 'mainController'
});
});
function HeaderController($scope, $location)
{
$scope.isActive = function (viewLocation) {
return viewLocation === $location.path();
};
}
asApp.run(['$rootScope', '$route', '$location', function($rootScope, $route, $location) {
$rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
document.title = 'Translation of ' + $route.current.params['word2lookup'] + ' | ' + $route.current.title;
});
}]);
asApp.controller('mainController', function($scope) {});
asApp.controller('dictController', function($scope, $routeParams){});
I don't even know if I can reproduce the entire situation in a fiddle since it involves some significant server-side scripting.
Please let me know if there's anything I could explain in order for someone to identify the gremlin breaking down my code's functionality.
P.S.: This issue only affects the first click (on any link on the page) after a new search has been performed, i.e. a word is entered in the input box and the Lookup button is clicked.
Update: In response to #gr3g's request, here's the code for the functions lookup_check() and lookup_word():
function lookup_check(lookupterm){
close_kb();
if(lookupterm != ""){
lookup_word(lookupterm);
}
else{
var lookup_box = $('#word');
lookup_box.addClass('empty');
setTimeout(function(){ lookup_box.removeClass('empty'); },500);
}
}
// Query dictionary and populate meaning div
function lookup_word(lookupword){
var mean = document.getElementById('meaning');
var waittext = '<div class="preloader-image"><br /><br />';
var hr = createXMLHTTPRequestObject();
var url = 'bootstrap/php/dictengine.php';
var vars = "lookup_word=" + lookupword;
document.getElementById('word').value = lookupword;
hr.open("POST", url, true);
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
hr.onreadystatechange = function(){
if(hr.readyState == 4 && hr.status == 200){
var return_data = hr.responseText;
mean.innerHTML = return_data;
if ($(".el")[0]){ hist_mean = $('.el:first').text(); }
else { hist_mean = ""; }
add2local(lookupword, hist_mean);
$(".tab-container").addClass("hide-tabs");
if($("#dict_span").length != 0) {
$(".tab-container").removeClass("hide-tabs");
// logic to seggregate spanish and english results
$("#dict_eng").addClass("hide-div");
$("#sp_tab").addClass("active");
$("#en_tab").removeClass("active");
}
document.title = 'Translation of ' + lookupword + ' | The thesite dictionary';
$("<hr class='dict-divider'>").insertAfter(".gram_cat");
$("<hr class='dict-divider'>").insertAfter(".quickdef");
$("<hr class='dict-divider'>").insertBefore(".dict_source");
$('div.entry_pos').wrap('<div class="pos"></div>');
$('a.dictionary-neodict-first-part-of-speech').wrap('<div class="pos"></div>');
// update url
var loc = window.location.href;
var lastpart = loc.substring(loc.lastIndexOf('/') + 1);
if(lastpart == 'dictionary'){ window.location.replace(window.location.href + "/" + encodeURI(lookupword)); }
if((lastpart != 'dictionary') && (lastpart != encodeURI(lookupword))){
var addr = window.location.href;
var addrtemp = addr.substring(addr.lastIndexOf('/') + 1);
addr = addr.replace(addrtemp, encodeURI(lookupword));
if(!!(window.history && history.pushState)){ history.pushState(null, null, addr); }
else{ window.location.replace(addr); }
}
}
//else { setTimeout('lookup_word(lookupword)', 1000); }
}
hr.send(vars);
mean.innerHTML = waittext;
}
Update 2: To further facilitate #gr3g, here's dictionary.html:
<!-- dictionary.html -->
<script>
var loc = window.location.href;
var lastpart = loc.substring(loc.lastIndexOf('/') + 1);
if(lastpart != 'dictionary'){ lookup_check(decodeURI(lastpart)); }
// populate search history if available
var recent = document.getElementById('recent-lookups');
var value = localStorage.getItem('w');
if (value) {
value = JSON.parse(value);
var len = value.length - 1;
var str = "";
for (a=len; a>=0; a--){
term = value[a].substr(0, value[a].indexOf('$'));
term_meaning = value[a].substr(value[a].indexOf("$") + 1);
if(term_meaning != "") {
str = str + "<p><strong><a href='/a-s/#/dictionary/" + encodeURI(term) + "'>" + term + "</a></strong> <i class='fa fa-chevron-right' style='color: #a5a5a5;font-size: 80%;'></i> <span class='recent_meanings'>" + term_meaning + "</span></p>";
}
else { str = str + "<p><em>" + term + "</em></p>"; }
}
recent.innerHTML = str;
}
else { recent.innerHTML = "<p>No historical data to show right now. Words will start appearing here as you begin your lookups.</p>"; }
// populate word of the day on pageload
wotd();
</script>
<!-- top-image start -->
<div class="page-header-line-div">
</div>
<!-- top-image end -->
<br>
<br>
<div class="container-fluid" ng-controller="luController as luCtrl">
<div class="row row-padding">
<form class="form-horizontal" role="form" name="lookup-form" id="lookup-form" action="" method="">
<div class="input-group col-md-6">
<input id="word" type="textbox" placeholder="Enter a Spanish or English word here..." class="form-control input-lg lookup-field lookup-field-single" onMouseOver="$(this).focus();" required ng-model="luCtrl.lookuptrm">
<i class="fa fa-times fa-lg delete-icon" onfocus="clearword();" onclick="clearword();" data-toggle="tooltip" data-placement="top" title="Click to clear entered text"></i>
<i class="fa fa-keyboard-o fa-2x kb-icon" onfocus="toggler('virtualkeypad', this);" onclick="toggler('virtualkeypad', this);" data-toggle="tooltip" data-placement="top" title="Click to enter accented characters"></i>
<div class="input-group-btn">
<button class="btn btn-lg btn-primary lookup-submit" type="submit" id="lookup" ng-click="luCtrl.handlelookup(luCtrl.lookuptrm)">Lookup</button>
</div>
</div>
<div id="virtualkeypad" class="btn-group vkb-hide"><!--col-md-offset-4-->
<button class="btn btn-lg first-btn" type="button" onClick="spl_character('á');">á</button>
<button class="btn btn-lg" type="button" onClick="spl_character('é');">é</button>
<button class="btn btn-lg" type="button" onClick="spl_character('í');">í</button>
<button class="btn btn-lg" type="button" onClick="spl_character('ó');">ó</button>
<button class="btn btn-lg" type="button" onClick="spl_character('ú');">ú</button>
<button class="btn btn-lg" type="button" onClick="spl_character('ü');">ü</button>
<button class="btn btn-lg last-btn" type="button" onClick="spl_character('ñ');">ñ</button>
</div>
</form>
<!-- tabbed view for bilingual words -->
<div class="col col-md-8 bi">
<ul class="nav nav-tabs tab-container hide-tabs lang-tabs" role="tablist">
<li class="nav active" id="sp_tab" onClick="$(this).addClass('active'); $('#en_tab').removeClass('active'); $('#dict_eng').addClass('hide-div'); $('#dict_span').removeClass('hide-div');">Spanish</li>
<li class="nav" id="en_tab" onClick="$(this).addClass('active'); $('#sp_tab').removeClass('active'); $('#dict_span').addClass('hide-div'); $('#dict_eng').removeClass('hide-div');">English</li>
</ul>
<div class="dictionary-result" id="meaning">
<p class="box-text">This bilingual dictionary is an actively growing resource accumulating new words each day. Currently drawing from the best names in the world of Spanish/English dictionary, such as <strong>Collins</strong><sup>®</sup> and <strong>Harrap</strong><sup>®</sup>, it continues to improve with every lookup you perform. It includes regionalism, colloquialism, and other non-standard quirkiness from over a dozen Spanish dialects ranging from Peninsular to Mexican and Argentinean to Cuban. This dictionary also includes a growing number of specialty terms specific to niches such as medicine, economics, politics, etc.</p>
<p class="box-text">Please use this page only for dictionary lookups and not comprehensive translations. You can enter either English or Spanish terms and the dictionary will automatically guess the language it belongs to. Keep your inputs to within 20 characters (that should be long enough to handle any English or Spanish word you might want to look up).</p>
</div>
</div>
<!-- sidebar -->
<div class="col col-md-4">
<!-- history panel -->
<div class="panel panel-default panel-box card-effect">
<div class="panel-heading panel-title">Recent Lookups</div>
<div id="recent-lookups" class="panel-body panel-text">
No historical data to show right now. Words will start appearing here as you begin your lookups.
</div>
</div>
<!-- WOTD panel -->
<div class="panel panel-default panel-box card-effect">
<div class="panel-heading panel-title">Word of the Day</div>
<div id="wotd" class="panel-body panel-text">
Word of the day not currently available.
</div>
</div>
</div>
</div>
</div>
Finally I got it to work!! The offending code was in the lookup_word() function:
if(!!(window.history && history.pushState)){ history.pushState(null, null, addr); }
else{ window.location.replace(addr); }
I just removed the if block and replaced it with history.pushState(null, null, addr); window.location.replace(addr);. Don't know why or how but this resolved the problem.
This :
.otherwise({
title: 'TheSite – Radical Spanish learning tips and tricks for the adventurous learner',
templateUrl : 'pages/home.html',
controller : 'mainController'
});
Can be replaced by this :
.otherwise("/");
In your HTML:
This should be avoided :
onclick="$('#word').blur(); lookup_check($('#word').val());"
You may put some JQuery events, but the values can't be passed from JQuery.
It should look something like that :
onclick="$('#word').blur(); lookup_check(variableValueBindToInput)"
Could you show the lookup_check function?
And also show how you make the call to the look_up function from the link?
Here is a Plunker, using your scripts, in the angular way.
http://plnkr.co/edit/EP8y7DrTmzr0WdRkQSew?p=preview
Look here for binding html.
Does
var loc = window.location.href;
var lastpart = loc.substring(loc.lastIndexOf('/') + 1);
if(lastpart != 'dictionary'){ lookup_check(decodeURI(lastpart)); }
Makes the XHR request on page load when the link is clicked (which is setting the request words in the url)?
If this is the case, can't you use:
str = str + "<a ng-click='lookup_checkFromLink(request)'>";
And don't check on page load?
Because, in AngularJs everything inside the app (#) does not reload the whole script when changing the route, which is a core concept of Single Page Applications : not reload all content when only a part of it needs to be changed.
I have a poll application, in which a user can vote for an option in a given poll. in the html template, i use ng-show to show weather the user has voted for this option or this poll or if its an unvoted poll for the user:
<div data-ng-repeat="option in poll.poll_options" class="list-group-item">
<span data-ng-if="option.option_thumb == '2'" class="glyphicon glyphicon-thumbs-up"></span>
<span data-ng-if="option.option_thumb == '1'" class="glyphicon glyphicon-thumbs-down"></span>
<div data-ng-show="optionVoted(option,authentication.user._id)">
<span data-ng-bind="option.option_text"></span>
</div>
<div data-ng-hide="optionVoted(option,authentication.user._id)">
<div data-ng-show="pollVoted(poll._id,votes)">
<a data-ng-click="updateVote()">
<span data-ng-bind="option.option_text"></span> - update
</a>
</div>
<div data-ng-hide="pollVoted(poll._id,votes)">
<a data-ng-click="createVote(poll,option,authentication.user._id,$index)">
<span data-ng-bind="option.option_text"></span> - new
</a>
</div>
</div>
<span class="option-votes"> - {{option.votes.length}}</span>
</div>
these are the above mentioned functions to determine if the option / poll has been voted by the user:
// check if option is voted
$scope.optionVoted = function(option,userId){
for (var i = 0; i < option.votes.length; i++){
if (option.votes[i].user === userId){
return true;
}
}
};
//check if poll is voted
$scope.pollVoted = function(pollId,votes){
for (var i = 0; i < votes.length; i++){
if (votes[i].poll === pollId){
return true;
}
}
}
and here is the function to create a new vote:
// create a vote
$scope.createVote = function(poll,option,userId,index){
var vote = new Votes({
user:userId,
poll:poll._id,
poll_option:option._id
});
vote.poll_option_id = option._id;
vote.$save(function(vote){
option.votes.push(vote);
$scope.$apply();
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
}
what happens on the front end, is that the option which has been now voted is updated (not showing an a tag anymore). what i need, is that the other options in the poll will update as well, and now instead of create() they will show update(), without refreshing the page.
how can I get the other html DOM elements of options in the poll to update?
In html, replace the functions in ng-show by an object property :
ng-show="option.voted", for example.
and update option.voted in createVote function.
(adapt this with userId etc.)
Make sure you are pushing the new vote onto the correct object in the scope. It looks like you are displaying data from $scope.poll.poll_options in your view, but you are adding to options.votes in your createVote function.