Split API to use its part as a variable - javascript

I am using an API that has a lot of different possible calls. I want to change a part of it in VUE so that depending on a different button different call is made.
https://api.themoviedb.org/3/movie/top_rated?api_key=<>&language=en-US&page=1
https://api.themoviedb.org/3/movie/upcoming?api_key=<>&language=en-US&page=1
Here are two different API calls that are possible and I want to make it so that it looks something like this:
"https://api.themoviedb.org/3/movie/" +variable+ "?api_key=<>&language=en-US&page=1"
and then depending on which button I pressed it would either make a call for "top_rated" or if another button is pressed it would be "upcoming"

You can use String literal ` ` to insert dynamic value.
<button #click="apiCall(true)">Upcoming</button>
<button #click="apiCall(false)">Top Rated</button>
...
methods: {
apiCall(isUpcoming) {
const apiType = isUpcoming ? 'upcoming' : 'top_rated';
const url = `https://api.themoviedb.org/3/movie/${apiType}?api_key=<>&language=en-US&page=1`;
// Fetch data with url.
...
}
}

There are many ways to archive this. Without the rest of the code I cannot suggest much.
Eventually you can create a method in your VUE component that returns the "top_rated" or "upconmig".
<template>
<button :href="'https://api.themoviedb.org/3/movie/' + getAction + '/?yourqueryparams'"></button>
</template>
<script>
export default {
name: 'Movie DB',
methods: {
getAction: function(){
return "top_rated"; //put condition here
}
}
}
</script>

I am not sure I understand your question, but maybe you need this:
vue template:
<button #click=handler('top_rated')>this is button no.1</button>
<button #click=handler('upcoming')>this is button no.2</button>
javascript:
methods: {
handler(type) {
const url = "https://api.themoviedb.org/3/movie/" + type + "?api_key=<>&language=en-US&page=1"
return fetch(url)
}
}

Related

Restcountries API - getting names of currencies dynamically into HTML through Javascript

I am new to Javascript and I've been learning how to import a country's attributes into an HTML element. Some of you might recognize this code, it's from a tutorial, which is now outdated. I've been searching around for an updated solution, but couldn't find any.
First I have the function to fetch the data:
const getCountryData = function (country) {
fetch(`https://restcountries.com/v3.1/name/${country}`)
.then(response => response.json())
.then(data => renderCountry(data[0]));
};
Then I call that function, supplying a country getCountryData('czechia') to infuse it into an element like this:
const renderCountry = function(data, className = '') {
const html = `
<article class="country ${className}">
<img class="country__img" src="${data.flags.svg}" />
<div class="country__data">
<h3 class="country__name">${data.name.common}</h3>
<h4 class="country__region">${data.region}</h4>
<p class="country__row">${(+data.population / 1000000).toFixed(1)} people</p>
<p class="country__row">${data.fifa}</p>
</div>
</article>
`
countriesContainer.insertAdjacentHTML
('beforeend', html);
countriesContainer.style.opacity = 1;
}
This works fine, but the issue is that at the end of the HTML, where I input {data.fifa} I want to have the name of the country's main currency instead. Unfortunately, the data is structured in a way, that in order to have the currency's name displayed, I first have to call it's short name, as shown below:
"currencies": {
"CZK": {
"name": "Czech koruna",
"symbol": "Kč"
}
},
If I call the {data.currencies} into the string, I'm just gonna get an empty object back. If I call it as {currencies.CZK.name}, it works, but the issue is that if I call Sweden, for example, it won't display anything, because then it'd need to be {currencies.SEK.name}. How do I get around this? How can I can call a currency's name without having to incorporate CZK, SEK, USD, EUR etc. into the variable?
Any help is appreciated.
You can transform that object into an array:
const currencyArray = Object.values(data.currencies)
console.log(currencyArray[0].name)
If the country has many currencies, just change the index from 0 to 1, 2, ...

JQuery, how to pass the slug variable

I'd like to know how I can pass the slug variable into JQuery/javascript.
I have a data-table with items, on each row there are two buttons, one (1) is using Django to create a product, the other (2) is supposed to use JQuery / JS to create a product.
To create a product with button 1 I find being straight forward and well explained.
I'd like to perform the same action on button 2, using JQuery/JS.
button 1
<button type="button" class="btn btn-secondary"><i class="fa fa-pencil"></i></button>
with urls path:
path("products/<uuid:slug>/create/", ProductsCreateView.as_view(), name="products-create"),
views.py
class ProductsCreateView(CreateView):
model = Products
template_name = "products_create.html"
slug_field = "products_uid"
button 2
<button class="btn btn-secondary js-create-button" data-url="{% url 'api-products-create' object.products_uid %}" type="button"><span class="fa fa-pencil"></span></button>
with urls path:
path('api/products/<uuid:slug>/create/', ProductsCreateView.as_view(), name="api-products-create"),
with js (truncated function)
$(function () {
var createProduct = function() {
var slug = '{{ $slug }}'; /* some code/function that gets hold of the slug */
const url = `/api/v1/products/${slug}/create/`;
$.get(url)
.done(function pollAsyncResults(data) {
// bind pollAsyncResults to itself to avoid clashing with
// the prior get request
context: this
// see the URL setup for where this url came from
const pollAsyncUrl = `/api/products/poll_async_results/${data.task_id}`;
})
};
$(".js-create-button").click(createProduct);
});
With help of #31piy answer to this SO post: How to console.log value of a data-attribute in jquery?
To select all the elements which have data-group attribute, you can
loop over the elements selected by the selector [data-group], and in
the iteration, get the value of the attribute using the data method.
Please see the example below:
$('[data-group]').each(function() {
console.log($(this).data('group'));
})
I figured out that the const url could be expressed as:
const url = $(this).data('url');
When logging it in the console, I will get the string I wanted
/api/products/7d49e267-f35d-4161-8eb5-0a815abbb083/create/
Thus, the complete code would become:
$(function () {
var createProduct = function() {
const url = $(this).data('url');
$.get(url)
.done(function pollAsyncResults(data) {
// bind pollAsyncResults to itself to avoid clashing with
// the prior get request
context: this
// see the URL setup for where this url came from
const pollAsyncUrl = `/api/products/poll_async_results/${data.task_id}`;
})
};
$(".js-create-button").click(createProduct);
});

How to dynamically show a button based on conditions where the value being used to determine what button to show isn't known until it's clicked?

If someone has a better title feel free to edit. I inherited a project from a developer who is leaving the company and I'm scratching my head trying to find a solution to a problem the existing code provides.
Code from the view:
<div>
<table class="table">
<tr>
<th class="border-bottom border-top-0">Action</th>
</tr>
#foreach (Step actionItem in Model.Steps)
{
#if (actionItem.HasRun == false)
{
<tr class="border-top-0">
<td>
#if (actionItem.ReturnsInfo == true)
{
<input type="button" value="Run Check" onclick="loadProcessingFeedbackPartial('#actionItem.StepID', '#Model.Client.DatabaseConnectionString' )" />
}
else
{
<input type="submit" value="Run Check" name="btnRunStoredProcedure" asp-action="CallStepStoredProcedure" asp-route-StepID="#actionItem.StepID" asp-route-StepCompleted="#actionItem.HasRun" />
}
</td>
</tr>
break;
}
}
</table>
</div>
Javascript being called from the button click:
<script type="text/javascript">
function loadProcessingFeedbackPartial(x, y) {
var url = '#Url.Action("ViewProcessingFeedBackPartial", "Client")';
var stepId = x;
var databaseConnectionString = y;
$("#processingFeedbackPartialDiv").load(url, { stepId, databaseConnectionString },
function () {
$("#confirmButton").removeAttr("style");
});
}
</script>
Controller action:
public IActionResult ViewProcessingFeedBackPartial(int StepId, string DatabaseConnectionString)
{
FeedbackDetails feedbackDetails = new FeedbackDetails();
feedbackDetails.Data = _clientProcessingService.GetProcessingFeedbackDetails(StepId, DatabaseConnectionString);
return PartialView("_ViewFeedback", feedbackDetails);
}
The button in the view has an Onclick event that goes to the Javascript function, which loads a partial view with the data from the controller calling a service method. Here's where the problem is. If no rows are returned, I want to bypass the partial being drawn entirely.
So I changed the controller action around a bit to include a condition where if the feedbackDetails.Data has 0 rows to just call a different method from the service, process as normal, but return the View instead of a partial.
public IActionResult ViewProcessingFeedBackPartial(int StepId, string DatabaseConnectionString, int ClientId)
{
FeedbackDetails feedbackDetails = new FeedbackDetails();
feedbackDetails.Data = _clientProcessingService.GetProcessingFeedbackDetails(StepId, DatabaseConnectionString);
if(feedbackDetails.Data.Rows.Count == 0)
{
_clientProcessingService.RunProcessStepConfirmation(DatabaseConnectionString, StepId, ClientId, "No information returned, automatically proceeding to next step.");
return RedirectToAction("Processing", new { Id = ClientId });
}
return PartialView("_ViewFeedback", feedbackDetails);
}
This "worked", except since in the view it's being called in a Javascript function that loads a partial regardless, the view is returned inside that partial instead of the view being returned.
But I'm unsure how to fix this because without first clicking the button and attempting to populate that collection with data, I don't know if it's empty (and skip the partial) or it has rows (and draw the partial).
I attempted creating an intermediary controller action that returns a boolean and attempted to use the result of that inside the javascript function to either draw the partial or skip it based on the bool, but I'm not really the greatest at Javascript so I wasn't able to get it to work.
I'm unsure if the way to solve this involves creating logic that displays multiple buttons that route to different controller actions or javascript functions or just handling it all via Javascript somehow.
What would be a good way to go about solving this?
#Mkalafut, your jQuery function is loading the controller result directly into "#processingFeedbackPartialDiv" regardless of the result received. Better to pull this initially into a variable, then add some simple logic to decide what to do next. Potentially the controller can help by returning a null result that is easy to identify.
e.g.
$.get("url", { stepId, databaseConnectionString }, function (data) {
var result = data;
// Some example conditional logic - adjust as required
if (result != null){
$("#processingFeedbackPartialDiv").html(result);
$("#confirmButton").removeAttr("style");
}
});
Remember, jQuery load & get are both just shorthand functions for ajax, so if needs be you can customise the code further to get the flexibility you need.
https://api.jquery.com/jQuery.get/
https://api.jquery.com/load/

Vue.js - Trouble displaying results from API call in component

Experimenting with Vue.js, trying to display results from a Wikipedia API call in a component using the v-for directive, but something is not working on the back end and I don't know what it is.
Link to the jsFiddle
HTML
<div id="app">
<input type="text" v-model="searchTerm" v-on:keyup="getResults">
<searchResult
v-for="item in results"
v-bind:result="item"
v-bind:key="item.key"
></searchResult>
</div>
Javascript
new Vue({
el: '#app',
data: {
api: "https://en.wikipedia.org/w/api.php?",
searchTerm: 'Ron',
searchDataString: "action=opensearch&format=json&origin=*&uselang=user&errorformat=html&search="+this.searchTerm+"&namespace=0%7C4&limit=20&profile=fuzzy",
searchCall: this.api+""+this.searchDataString,
results: []
},
methods: {
getResults() {
this.searchCall = this.api+"action=opensearch&format=json&origin=*&uselang=user&errorformat=html&search="+this.searchTerm+"&namespace=0%7C4&limit=20&profile=fuzzy";
//console.log( this.searchCall );
axios.post( this.searchCall )
.then(response => { this.processResults(response.data) });
},
processResults(data) {
//console.log( data );
for(var i = 0; i < data[1].length; i++) {
var resultItem = { key:i, link:data[3][i], name:data[1], description:data[2][i] };
this.results.push(resultItem);
console.log(resultItem);
}
}
}
});
Vue.component( "searchResult", {
props:['result'],
template: "<a target='_blank' href='{{ result.link }}'><div class='search-result'><h3>{{ result.name }}</h3><p>{{ result.description }}</p><div></a>"
});
The two issues on my mind are
the error message that shows in the console when typing input, and
that the array of results is creating empty objects instead of passing the data
When I look at the array in the console, all it shows are getters and setters. I'm new to this, so maybe that's what it's supposed to be doing.
I'm so close to getting this working, but I'm at my wits end, help is much appreciated.
The problem with your code is that html tags aren't case sensitive so naming a component searchResult causes issues. If you need to use searchResult, you'll have to use <search-result> in your template. I find it better just to avoid the problem altogether and give components lower-case names. Here are docs about the issue: https://v2.vuejs.org/v2/guide/components.html#Component-Naming-Conventions
You mentioned "the error message that shows in the console when typing input". I didn't get any errors copying and pasting your code (other than forgetting to include axios). What error are you getting?

Multiple button calling same function with different parameters in angularjs - javascript

I want to call same method in controller on multiple button click with different parameters. If I write different-different javascript code to handle it, works fine. But I want to use the same code for all operation... Here is html code:
Note: "breakfastCalorie" and "lunchCalorie" are available dynamic values.
<div id="breakfast">
<span> Breakfast - {{breakfastCalorie}} </span>
<button id="breakfast_btn" ng-click="suggestMeal(breakfastCalorie)">Breakfast</button>
</div>
<div id="lunch">
<span> Lunch - {{lunchCalorie}} </span>
<button id="lunch_btn" ng-click="suggestMeal(lunchCalorie)">Lunch</button>
</div>
... and so on.
And the following function should be called on each button click (or should I write same javascript again).
Here is javascript line of code:
$scope.suggestMeal = function () {
//I want the calorie value to further send it to do some manipulation
}
You can create enum for type of eat
$scope.EatType = {
breakfast: 1,
lunch: 2
};
Then call with appropriate type:
$scope.suggestMeal = function (eatType, cal) {
}
for calling:
<button id="lunch_btn" ng-click="suggestMeal(EatType.lunch,lunchCalorie)">Lunch</button>

Categories

Resources