WP Rest API Get Featured Image - angularjs

I am building a relatively simply blog page that uses the WP Rest Api and AngularJs to show the data on the front-end.
On my home page I want to return the title, followed by the featured image, followed by the excerpt. I have pulled the title and excerpt in fine it seems that in the JSON the featured image is a media Id. What is the best way to pull this data in on the fly?
I have seen various things around the internet that use PHP functions but I think the best way to do it is within a angular controller, just looking for some advice on exactly what the controller would be
List View HTML
<ng-include src=" dir + '/form.html?v=2' "></ng-include>
<div class="row">
<div class="col-sm-8 col-lg-10 col-lg-push-1 post">
<div class="row-fluid">
<div class="col-sm-12">
<article ng-repeat="post in posts" class="projects">
<a class="title" href="#/post/{{post.slug}}"><h2>{{post.title.rendered}}</h2></a>
<p ng-bind-html="post.excerpt.rendered | to_trusted"></p>
</article>
</div>
</div>
</div>
</div>
Controller
.controller('listPage',['$scope','Posts', function($scope,Posts){
$scope.refreshPosts = function(){
Posts.query(function(res){
$scope.posts = res;
});
};
$scope.refreshPosts();
// CLEARFORMFUNCTION
$scope.clear = function(){
$scope.$root.openPost = false;
jQuery('#save').modal('hide');
};
// SAVEMODALOPEN/COSE
$scope.openSaveModal = function(){
jQuery('#save').modal('show');
}
$scope.closeSaveModal = function(){
jQuery('#save').modal('hide');
}
// DATEFUNCTION
$scope.datify = function(date){
$scope.date = newDate(date);
return $scope.date.getDate()+'/'+$scope.date.getMonth()+'/'+$scope.date.getYear();
};
}])

You could also modify the JSON response with PHP. This returns just what I need and is very fast (Using _embed is very slow in my experience)
I have the following code in a plugin (used for adding custom post types), but I imagine you could put it in your theme's function.php file.
php
add_action( 'rest_api_init', 'add_thumbnail_to_JSON' );
function add_thumbnail_to_JSON() {
//Add featured image
register_rest_field( 'post',
'featured_image_src', //NAME OF THE NEW FIELD TO BE ADDED - you can call this anything
array(
'get_callback' => 'get_image_src',
'update_callback' => null,
'schema' => null,
)
);
}
function get_image_src( $object, $field_name, $request ) {
$size = 'thumbnail'; // Change this to the size you want | 'medium' / 'large'
$feat_img_array = wp_get_attachment_image_src($object['featured_media'], $size, true);
return $feat_img_array[0];
}
Now in your JSON response you should see a new field called "featured_image_src": containing a url to the thumbnail.
Read more about modifying responses here:
http://v2.wp-api.org/extending/modifying/
And here's more information on the wp_get_attachment_image_src() function
https://developer.wordpress.org/reference/functions/wp_get_attachment_image_src/
**Note: Don't forget <?php ?> tags if this is a new php file!

Turns out, in my case, there is a new plugin available that solves this without having to make a secondary request. See my recent Q:
WP Rest API + AngularJS : How to grab Featured Image for display on page?

If you send the ?_embed param to the query, it will return more information in the response, like images, categories, and author data.
const result = await axios.get(`/wp-json/wp/v2/my-post-type?_embed`);
// Featured Image
result.data._embedded['wp:featuredmedia'][0].source_url;
// Thumbnail
result.data._embedded['wp:featuredmedia'][0]['media_details']['sizes']['medium']['source_url']

Related

How to read attribute "name" of my json array in Ionic

json array localstorage format
Hello, I'm developing an ionic app. I'm new in Ionic and Typescript.
As you can see in the image below I'm parsing from an API my data in a json array.
On ts file I'm writing this code
`
public categoryDetails:any;
const datacat = JSON.parse(localStorage.getItem('categoryData'));
this.categoryDetails = datacat.categoryData;`
And in my html file when I write this
<h1 class="business-top">Business of the category {{categoryDetails.name}}</h1>
I get the error message "TypeError: Cannot read property 'name' of undefined"
I know that I don't read the attribute "name" correctly. How can I do this one?
Moreover, how can I display Businesses which associate with the spesific term_id of the category?
In this example you need to do that
<h1 class="business-top">Business of the category {{categoryDetails?.name}}</h1>
public categoryDetails: any;
this.categoryDetails = localStorage.getItem('categoryData');
or you can use ionic storage. it is better if you are using ionic.
https://ionicframework.com/docs/storage/
import { Storage } from '#ionic/storage';
export class MyApp {
public categoryDetails: any;
constructor(private storage: Storage) { }
...
// set a key/value
storage.set('categoryData', 'Max');
// Or to get a key/value pair
storage.get('categoryData').then((val) => {
this.categoryDetails = val;
});
}
I finally fingured it out.
#Kilomat thanks for your help and your advice about using ionic storage. That saved me from futured problems.
About my json file that's what I did.
In my HTML code
<ion-grid no-margin>
<h1 class="business-top">Επιχειρήσεις της κατηγορίας {{businessData.name}} {{businessData.term_id}}</h1>
<ion-list>
<ion-item class="col col-50" *ngFor="let c of BusinessCategoryDetails" text-wrap (click)="product(c)">
<div *ngIf="c.term_id == businessData.term_id">
<h2>{{c.post_title}} {{c.term_id}}</h2> <img width="80" height="80" src="{{c.guid}}">
</div>
</ion-item>
</ion-list>
</ion-grid>
And in my TS code
`var businessCategory: categories = navParams.get("businessCategory");
console.log(businessCategory); /exports the Selected category/
var newData = JSON.stringify(businessCategory);
this.businessData = JSON.parse(newData);`
Which takes properties and values from my previous category page. TS code
`categories: [categoryDetails] = null;
gotobusiness(category: categories){
this.navCtrl.push(BusinessPage, { businessCategory: category});
}`

Filter card list with Razor View

Im trying to make a filter like in AngularJS when u use:
ng-repeat="u in users | filter:searchBar">
And your input filter looks like
<input type="text" id="searchBar" placeholder="start typing" ng-model="searchBar">
But the things its that im working on MVC with Razor View and I do not know how to approach this filter.
The list of cards is made with a foreachlike this:
#foreach{ var item in Models){
<div class="card">
<div class="card-container">
some content
</div>
</div>
}
Any ideas?
You can do the filtering with ajax. Here is a server side filtering solution.
First, you should move the code which renders the result to a partial view. Let's say you created a partial view called CustomerList.cshtml. Move the list code to that.
#model IEnumerable<Customer>
#foreach (var item in Model)
{
<div class="card">
<div class="card-container">
#item.Name
</div>
</div>
}
Now in your main view, you can call this partial view and pass the data to it. Wrap the call to the partial view in a container div. Add a input element for user to enter the search key. Assuming your main view is also strongly typed to IEnumerable<Customer>
#model IEnumerable<Customer>
<input type="text" id="search" data-url="#Url.Action("Index")" />
<div id="div-items">
#Html.Partial("CustomerList",Model)
</div>
Now we need to have some javascript code which listen to the keyup event on the search input, read the value of it and make an ajax call to the server where it uses the search key and get the filtered set of data, pass that to the same partial view and return the partial view result.
You can use jQuery $.get method
$(document).ready(function () {
$("#search").keyup(function() {
var v = $(this).val();
$.get($(this).data("url"), { searchKey: v }).done(function(res) {
$("#div-items").html(res);
});
});
});
Now make sure your server action method returns the filtered data like this
public ActionResult Index(string serchKey="")
{
var items = db.Customers.AsQueryable();
if (!String.IsNullOrEmpty(searchKey))
{
items = items.Where(a => a.Name.StartsWith(searchKey));
}
var t = items.ToList();
if (Request.IsAjaxRequest())
{
return PartialView("CustomerList",t );
}
return View(t);
}
Another option is to do client side filtering. on the items. But if i am going that direction, i would choose a client side MVC framework like angular to do that for me

Laravel - Get parameter from URI and receive database info based on that parameter

I'm working with laravel and I need to get a username from URL and then get info based on that from database, I don't have any idea as how to achieve this. Can someone help me out here?
Route::get('/profile/{username}', 'ProfileController#show');
And I have no idea how to call this in the controller and send it in the view, and then how to call things in the view.
public function show($username)
{
User::where('username', $username)->get();
return view('profile/index', ['username' => $username]);
}
How can I display stuff from that row in the view?
Thanks already!
To display data of that user try with the following code.
projectname/app/Http/routes.php
Route::get('/profile/{username}', 'ProfileController#show');
projectname/app/Http/Controllers/ProfileController.php
public function show($username)
{
$user_data = User::where('username', $username)->first();
return view('profile.index', ['username' => $username, 'user_data' => $user_data]);
}
projectname/resources/views/profile/index.blade.php
<div class="container">
<div class="row">
<ul>
<li>Username: {{ $username }}</li>
<li>Name: {{ $user_data->name }}</li>
</ul>
</div>
</div>
Please Note: I have assumed that username is unique; so I have used first() and you have username, name fields in table which is associated with User Modal.
Above code is tested and working on Laravel 5.2. and on above given assumptions.
Hope it helps you.
You should read about controllers and routes. Your controller should look like this:
public function show($username)
{
User::where('name', $usename)->get();
Here $username variable will contain {username} part from URI.

How to retrieve nested json object data with Ionic

I am working with the api from The Movie Database. In my Ionic project I was able to make a http request to pull in some data for a movie. However the json object is a nested json object, so I am having some trouble trying to access the genres of a movie:
For the purpose of this question I will display 1 nested json object:
I want to show the information like so -> Genre: Action - Comedy - Drama
My code for the controller is the following:
$scope.init = function(){
MovieService.getMovieById($stateParams.id).then(function(data){
$scope.trending_movie = data;
console.log($scope.trending_movie);
$scope.genres = data.genres;
console.log($scope.genres);
});
}
If I do this bit of code:
$scope.genres = data.genres;
It just returns met the json object of the genres like so:
The thing is now that I am able to read out the genres but because I access the data with a ng-repeat it will show like this:
How to get the genres on 1 line without having to repeat the word "Genre"?
Here is my html code:
<div ng-repeat="genre in genres">
<p class="movie-info-p">Genre: {{genre.name}}</p>
</div>
you should get "Genre:" out of your ng-repeat and if you want your genres to be in the same line, you shouldn't put them in tag.
There is this solution:
<div> Genre:
<div ng-repeat="genre in genres">
<span class="movie-info-p">{{genre.name}}</span>
</div>
</div>
Another solution is to generate this string in the controller with a for loop and send it to the view

Changing the template data not refreshing the elements

I have searched and tried suggestions mentioned in various posts but no luck so far.
Here is my issue.
I have created a custom element <month-view id="month-view-element"></month-view> in my mainpage.html. Inside mainpage.html when this page is initially loaded i created a empty json object for all the 30days of a month and print a placeholder type cards in UI. Using the code below.
var json = [];
for(var x = 0; x < total; x++) {
json.push({'hours': 0, 'day': x+1, 'year': year});
}
monthView.month = json; //Doing this line. Prints out the desired empty cards for me in the UI.
created a month-view.html something like below:
<dom-module id='month-view'>
<template>
<template is="dom-repeat" items= "{{month}}">
<paper-card class="day-paper-card" heading={{item.day}}>
<div class="card-content work">{{item.work}}</div>
<div class="card-actions containerDay layout horizontal">
<div style="display:inline-block" class="icon">
<paper-icon-button icon="icons:done" data-hours = "8" data-day$="{{item.day}}" data-month$={{item.month}} data-year$={{item.year}} on-click="updateWorkHours"></paper-icon-button>
<paper-tooltip>Full day</paper-tooltip>
</div>
</div>
</paper-card>
</template>
</template>
<script>
Polymer({
is: "month-view",
updateWorkHours: function (e, detail) {
console.log(e);
this.fire('updateWorkHour', {day: e.target.dataHost.dataset.day,
month: e.target.dataHost.dataset.month,
year: e.target.dataHost.dataset.year,
hours: e.target.dataHost.dataset.work
});
}
});
</script>
</dom-module>
There is another file script.js which contains the function document.addEventListener('updateWorkHour', function (e) { // doStuff });. I use this function to make a call to a google client API. I created a client request and then do request.execute(handleCallback);
Once this call is passed i landed in handleCallback function. In this function i do some processing of the response data and save parts of data into json variable available in the file already. And once all processing is done i did something like below.
monthView.month = json;
But this above line is not refreshing my UI with the latest data. Is there anything I am missing? Any suggestions or anything i am doing incorrectly.
You need to use 'set' or 'notifyPath' while changing Polymer Object or Arrays in javascript for the databinding/obserers to work. You can read more about it in https://www.polymer-project.org/1.0/docs/devguide/data-binding.html#path-binding
In your case try below code
monthView.set('month',json);
Updated suggestions:
Wrap your script on main page with. This is required for non-chrome browsers.
addEventListener('WebComponentsReady', function() {})
This could be scoping issue. Try executing 'document.querySelector('#month-view-element');' inside your callback addWorkHoursCallBack. Also, Use .notifyPath instead of .set.

Resources