AngularJS rendering the content fine into title and meta tags, but when I share it with facebook or google, in the popup window it shows angular {{ }} there.
Code:
<div ng-controller="MyCtrl">
<title>{{mDetails.display1}} - Subtitle</title>
<meta name="description" content="{{mDetails.display1}} - {{mDetails.address1}} , {{mDetails.city}}, {{mDetails.state}}, {{mDetails.country}}">
.
.
Note: I am already using ng-cloak.
Thanks for help.
Two ways, as mentioned on another question :-
og meta tags, social buttons and angularjs
Method 1 :-
This can't be done using javascript. Some people think that Facebook is reading what's currently on the page. It's not. It makes a separate request to your server using the same url (from window.location.href) using it's Scraper, and the Facebook Scraper does not run javascript. That's why you get {{page_title}} when clicking on something like a Facebook share button. Your content will have to be generated by the server so when Facebook goes to hit the url it gets the content it needs up front without the need for javascript. You can tackle the server side rendering in a fews ways.
You can allow your server side technology to render the content.
You can use the PhantomJS approach https://github.com/steeve/angular-seo.
Method 2 :-
There's also a possibility that you can re-render Facebook widgets. Use their parse method:
FB.XFBML.parse();
after your angular stuff has completed. It's not working for my share button (yet!!), but I tested it on likes, and it's cool. Basically it re-scans the DOM and renders the Facebook widgets. You can also pass it a single element, something like this directive:
'use strict';
angular.module('ngApp')
.directive("fbLike", function($rootScope) {
return function (scope, iElement, iAttrs) {
if (FB && scope.$last) {
FB.XFBML.parse(iElement[0]);
}
};
});
This snippet would rescan the DOM for html5 facebook fb-like widgets when creating the last element in angular repeater.
Another accepted answer in the same context :-
https://stackoverflow.com/a/24086652/1366216
Edit:
I implemented json on server side just for the meta tags, however its an overhead because for on page data, there is still ajax call.
$mid=$_GET['id'];
$mJSON = file_get_contents($homeurl."/json/getdetail.php?mid=".$mid);
$mObject = json_decode($mJSON, true);
if ($mObject['ID'] != undefined && $mObject['ID'] != '') {
<meta property="og:title" content="<?php echo $mObject['display1'];?>"/>
<meta property="og:description" content="<?php echo .$mObject['display2']; ?>"/>
}
A possibility that worked for me is to have a "fallback" for FB description (so it would be a generic description that shows when angular hasn't loaded). I achieved this using two ng-if.
<meta ng-if="mDetails.display1" property="og:title" content="{ mDetails.display1 + "- Subtitle"}}">
<meta ng-if="!mDetails.display1" property="og:title" content="A generic title">
Whenever there are two meta descriptions with the same title, FB will take the last one. And after rendering, googlebot will only see the non-default one.
Related
I have seen this question in STO but could not find a proper answer.
I am using angular 1.0 and sending an AJAX request to server to get a list of URLs like below format:
https://www.abc.info/tawasol-news/20830168
https://www.abc.info/tawasol-news/20830169
https://www.abc.info/tawasol-news/20830174
and I want to load these URLs in a set of div tags down another.
but I can not see a clear solution how achieve that. please help to to load these URLs inside a div where we can scroll and view item by item.
Thank you
One solution is using object element in your HTML (div).
<object type="text/html" data="your url"></object>
See Mozilla documentation for object here.
I have previously created a web app, and now I would like to integrate it with OnsenUI to enable my app to be used on all mobile devices as well as the web.
I am using a splitter in a toolbar which will be the header of all pages, and it will redirect the user to other pages when they click an item in it. Clicking the home item successfully redirects to the home page (index, which is already loaded correctly). However, clicking any of the other items in the splitter redirects me to the requested page, but shows the content of the file in text format instead of actually rendering the page. It looks like the following, except it's all jumbled together with no spaces:
searchForTrainer.jade:
//-ons-template(id='searchForTrainer.jade')
ons-page(ng-controller='SearchController' ng-init='showme = false; getAllTrainers();')
ons-toolbar
.left
ons-toolbar-button(ng-click='mySplitter.left.open()')
ons-icon(icon='md-menu')
.center
| Search Trainer
// ***** I cut off the rest of the file for simplicity
// ***** I should still be able to see the toolbar if the page loads correctly
Here is the content of index.jade:
doctype html
html
head
link(rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css')
link(rel='stylesheet', href='/stylesheets/style.css')
link(rel='stylesheet' type='text/css' href='/stylesheets/jquery.datetimepicker.css')
link(rel='stylesheet' type='text/css' href='/stylesheets/ratings.css')
link(rel='stylesheet' type='text/css' href='/stylesheets/searchTrainerTab.css')
link(rel='stylesheet' type='text/css' href='/onsenui/css/onsenui.css')
link(rel='stylesheet' type='text/css' href='/onsenui/css/onsen-css-components.css')
block loadfirst
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js')
script(src="https://code.jquery.com/jquery-1.12.3.min.js"
integrity="sha256-aaODHAgvwQW1bFOGXMeX+pC4PZIPsvn2h1sArYOhgXQ=" crossorigin="anonymous")
script(src='/onsenui/js/onsenui.js')
script(src='/onsenui/js/angular-onsenui.js')
script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js')
script(src='/angular/fitnessapp.js')
script(data-require='angular-credit-cards#*', data-semver='3.0.1', src='https://rawgit.com/bendrucker/angular-credit-cards/v3.0.1/release/angular-credit-cards.js')
script(async='', defer='', src='https://maps.googleapis.com/maps/api/js?key=AIzaSyDcVf7YAPNwa8gUsMCOZNQZA31s5Ojf2n8&libraries=places')
body
ons-splitter(var='mySplitter', ng-controller='RootController as splitter')
ons-splitter-side(side='left', width='220px', collapse='', swipeable='')
ons-page
ons-list
ons-list-item(ng-click="splitter.load('index.jade')", tappable='')
| Home
ons-list-item(ng-click="splitter.load('searchForTrainer.jade')", tappable='')
| Search Trainer
ons-list-item(ng-click="splitter.load('searchForEvent.jade')", tappable='')
| Search Event
ons-list-item(ng-click="splitter.load('trainerAddEvent.jade')", tappable='')
| Create Event
ons-list-item(ng-click="splitter.load('userProfile.jade')", tappable='')
| Profile
ons-list-item(ng-click="splitter.load('addPayment.jade')", tappable='')
| Payment
ons-list-item(ng-click="splitter.load('userSettings.jade')", tappable='')
| Settings
ons-list-item(ng-click="splitter.load('trainerSignup.jade')", tappable='')
| Trainer Application
ons-list-item(ng-click="href='/logout'", tappable='')
| Logout
ons-splitter-content(page='index.jade')
ons-template(id='index.jade')
ons-page(ng-controller='MapController' ng-init='getEvents()')
ons-toolbar
.left
ons-toolbar-button(ng-click='mySplitter.left.open()')
ons-icon(icon='md-menu')
.center
| Fitness App
//-.right
a(href='https://www.paypal.com/webapps/mpp/paypal-popup', title='How PayPal Works', onclick="javascript:window.open('https://www.paypal.com/webapps/mpp/paypal-popup','WIPaypal','toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=1060, height=700'); return false;")
img(src='https://www.paypalobjects.com/webstatic/mktg/logo/bdg_now_accepting_pp_2line_w.png', border='0', alt='Now Accepting PayPal')
//- google maps stuff
ons-input#pac-input.controls(type='text', placeholder='Search Box')
div#map.col-md-12
ons-bottom-toolbar
.center
| Fitness App
block scripts
script.
// ***** I cut out javascript related to Google Maps for simplicity
here is the splitter load page function I am using in my angular file:
this.load = function(page) { console.log("The page is: " + page);
mySplitter.content.load(page)
.then(function() {
mySplitter.left.close();
});
};
Has anyone successfully built an Onsen app using Jade?
UPDATE
When I leave the code in html instead of jade, everything works correctly. When I convert it back to jade it shows up as text again.
UPDATE 2
Using Solution 1 from the selected answer, I realized and solved my problem with the guidance from the selected answer on my other post:
Answer
By the looks of it you seem to be using Jade on the server side.
To solve the problem I see a couple possible solutions.
Solution 1:
Make sure that whatever Onsen UI is receiving is pure HTML. You're free to use Jade, but as it stands Onsen does not have Jade bundled inside, so there is no way for it to support it out of the box. However as long as Onsen sees only html it should be fine.
The reason why the ons-template(id='index.jade') works initially is actually because when you serve the page you are actually serving actual html, so when onsen starts the contents of that template are actually pure html.
In searchForTrainer.jade it seems that you are giving it raw jade, which it does not know how to handle. You can handle this on the server side, making sure that the request for the searchForTrainer returns html. Returning jade.renderFile('searchForTrainer.jade') from the server instead of the jade file itself should solve the issue.
Solution 2:
As you noticed as long the contents are inside the initial page everything will be fine. So you could just put all your ons-templates inside the initial page.
If you want to retain your current file structure you can just do
include searchForTrainer.jade
while having an ons-template tag in the file itself. That way in the end the result will be a page with the template already converted into html.
Solution 3:
The final option is to give the raw jade files, but help Onsen understand Jade, so that it can use them properly. To do that you need to include jade.js and modify Onsen UI so that it uses it.
However since Onsen does not currently provide an official API for switching template engines whatever hack we use now might break in the future. It's possible that in the near future a feature like that may be implemented, but in order to do it now we need to wrap some of onsen's internal functions.
Here's a simple example to do it.
module.run(function($onsen) {
var old = $onsen.normalizePageHTML;
ons._internal.normalizePageHTML = $onsen.normalizePageHTML = function(html) {
return old(jade.render(html, {}));
};
});
And here's also a working Demo showing this solution in action.
Note: that demo actually checks for a comment // jade at the beginning just to be safe.
Which solution to choose?
Solution 1 - I think this makes most sense as it retains a clear separation of concerns. If you want to change the templating engine it should be handled only in one place. Onsen does not need to know what you're using on the server as long as it gets what it wants.
Solution 2 - Not the best way to solve the problem, but it may be the easiest to use if you just want things to work. One minus is that with it you would load all the templates at the beginning, which may not be very good.
Solution 3 - While this solution can work I would suggest avoiding it as handling jade on the frontend would result in poor performance. It's could be an option if you actually decide not to rely on the server.
I want to be able to set the href dynamically with AngularJS. The below works only if the custom field is the only one assigned. If there are multiple custom fields, the below will not work. I am new to AngularJS. Do you know what else I could do?
<link rel="shortcut icon" href="{{user.CustomFields[0].File.Url}}">
The correct way to write this is using the ngHref directive.
<link rel="icon" ng-href="{{user.CustomFields[0].File.Url}}">
Using Angular markup like {{hash}} in an href attribute will make the link go to the wrong URL if the user clicks it before Angular has a chance to replace the {{hash}} markup with its value. Until Angular replaces the markup the link will be broken and will most likely return a 404 error. The ngHref directive solves this problem.
ngHref Documentation
Note: a similar scenario occurs when using img tags. You should use ngSrc in that case
I am attempting to create a SPA using AngularJS as the main view for my website. I'm using ServiceStack on the server-side and can therefore cleanly serve HTML or JSON requests depending on what's accessing it. My main concern is the use of script blockers, preventing AngularJS from rendering the page properly. So far my main way of working is to render static pages, and inject a small script that redirects to the AngularJS-powered pages if it detects if Javascript is enabled. This works great since every URL works fine when the user begins at the static pages, but I've ran into a couple of snags.
Browsing to a link which includes the "?View=SPA" breaks the page if JavaScript is disabled
This causes the first page loaded to be loaded twice.
I'm looking for an alternative, but so far I haven't found any clean solutions. I was thinking about including the "?View=SPA" as a POST variable, but I'm still iffy on that implementation.
Any thoughts?
Instead of redirecting to an other page, I would implement both cases in the same HTML File as follows:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<style>.hideIfNoScript {display: none}</style>
</head>
<body ng-app ng-init="msg = 'hello world'">
<input class="hideIfNoScript" ng-model="msg" />
<p class="hideIfNoScript">{{msg}}</p>
<noscript>
<p>Content without javascript</p>
</noscript>
<script type="text/javascript">
var myEl = angular.element( document.querySelectorAll( '.hideIfNoScript' ) );
myEl.removeClass('hideIfNoScript');
</script>
</body>
</html>
The CSS Class hideIfNoScript in the head section makes sure that all HTML Tags with this class are never shown to the user, if javascript is disabled.
The noscript tag shows the alternative content.
If javascript is enabled, the little script at the end of the body section makes those elements visible. And in this case, the contents of the noscript tag are hidden.
Browsing to a link which includes the "?View=SPA" breaks the page if JavaScript is disabled
Hide those links by default:
a[href*='SPA'] { display: none; }
This causes the first page loaded to be loaded twice
Use a cookie on a browser-check page which loads the first page in an iframe or redirects to it to avoid this.
References
Track Non-JavaScript Visits In Google Analytics
I have a silverlight application where users can type in a SQL-query in the application, then the server returns the query result as an Excel file.
Users click on a download link, which is linked to a HttpHandler in the server which generates the excel file. After some research[1] I found out that using the HyperlinkButton control is the most robust way of providing links to file without the hassles of browser's popup security settings.
I need to send the SQL query, which can get quite long, as a parameter to the HttpHandler.
I can't include it in the url as querystrings(HTTP GET) due to size limitations.
Is there a way to do a 'HTTP-POST' with HyperlinkButton?
[1] Browser.HtmlPage.Window.Navigate is blocked but HyperlinkButton isn't - why?
In that case I think you can try sending a get/post request using jquery.
Post request API documentaton: http://api.jquery.com/jQuery.post/
Get Request API documantation: http://api.jquery.com/jQuery.get/
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js">
</script>
<script>
function f(){
$.post("http://www.w3schools.com/jquery/demo_test_post.asp",
{
name:"Donald Duck",
city:"Duckburg"
},
function(data,status){
alert("Data: " + data + "\nStatus: " + status);
}
)};
</script>
</head>
<body>
Send an HTTP POST request to a page and get the result back
</body>
</html>
Instead of Using Links Why just you make the buttons look like Links instead. One perfect example of buttons been shown as links is the Facebook. It has several number of buttons in a post, but all of them are shown as links. Here is the Css Code that what it makes a button look like a link. You can always change the look and feel of the link(perhaps Button).
Here the css code for the button.
button {
background:none!important;
border:none;
padding:0!important;
/* Do all your Styling to the Button here. It will look like a link instead. */
}
Button HTML Code.
<button>Your Button Here.</button>
Hope that Solves your Problem. Thank You.