Repeating Dataset from API response in Wix Code - velo

How can I repeat the display of response from API in Wix?
I have the following code in my backend module that queries the API for data like so:
export function getTopCoins() {
const url = 'https://api.coinmarketcap.com/v1/ticker/?limit=10';
return fetch(url, {method: 'get'})
.then(response => response.json());
}
and then in the frontend, I want to render it in the browser like so:
export function page1_viewportEnter(event, $w) {
getTopCoins().then(response => {
response.forEach(($w, itemData, index) => {
$w('#coinList').text = itemData.name;
});
});
}
So basically I have a Paragraph element with the ID of name coinList. So as you can see I want to display a list of names of the top 10 coins from coin market cap. How can I achieve this?
A working version of this was one that displayed the name of the first item on the list, this is the code:
export function page1_viewportEnter(event, $w) {
getTopCoins().then(response => {
$w('#coinList').text = "Name: " + response[0].name + "\n";
});
}

You can use the (pretty new) feature of Wix called Repeaters. Its in a Beta phase at the moment. You may find it under Add Panel --> Lists & Grids...
Then, in Wix Code IDE, you may write something like that (assuming you connected all the proper data binding with the connect panel configuration between you dataset and the repeater component:
export function page1_viewportEnter(event, $w) {
getTopCoins().then(response => {
$w('#repeater1').data = response;
});
}
You may refer to the Repeater API here.
One more thing, if I'm allowed to suggest: if you don't have any backend logic when calling getTopCoins from your backend code, you may use Wix Fetch API in you frontend code directly and save a network hop (faster and better performance)
Enjoy!

Related

Howto add a custom link provider

In the latest release of vscode (1__49), there is a code snippet on creating a new link provider. https://code.visualstudio.com/updates/v1_49. I can't seem to find a reference on where to apply this code.
window.registerTerminalLinkProvider({
provideTerminalLinks: (context, token) => {
// Detect the first instance of the word "test" if it exists and linkify it
const startIndex = (context.line as string).indexOf('test');
if (startIndex === -1) {
return [];
}
// Return an array of link results, this example only returns a single link
return [
{
startIndex,
length: 'test'.length,
tooltip: 'Show a notification',
// You can return data in this object to access inside handleTerminalLink
data: 'Example data'
}
];
},
handleTerminalLink: (link: any) => {
vscode.window.showInformationMessage(`Link activated (data = ${link.data})`);
}
});
What is the process for getting the editor to utilize this feature?
You will need to create a vscode extension that includes your code.
As it so happens, I have just set up a fresh extension that will use the TerminalLinkProvider. You can take a look at how the sample code integrates into a sample extension on GitHub.
A good place to start with your first extension is the official guide.
After that, just add your code to the activate(...) function of your extension.
You can built your extension as a .vsix file and install it in any vscode instance you use, but if you think that your code might be of value to others, consider publishing it!

How to route ASP.Net Core api return value to appropriate observable based on data type returned

I have created an ASP.NET Core Web Api backend with an Angular 7 frontend. One of the methods in the Api can return either an object or an array to an Angular service. How do I route to specific observable, based on the data type returned? I am a noob to Angular, so any kind assistance would be appreciated.
Angular service call to Api:
getLinksFromSitus(situs: any) {
this.http.post(this.baseUrl + 'getLinksFromSitus', situs).subscribe(data =>
this.apiData.next(data)
);
}
Portion of Web Api that returns array if more than one APN present:
// if more than one item in list, get status information for each and return list to user to select appropriate apn
if (propApn.Count > 1)
{
return Ok(propApn);
}
Portion of same method to return object if only one value for APN:
var resultsModel = new Results
{
ArcGisLink = arcGisLink,
HistInfoLink = histInfoLink,
PropInfoLink = propInfoLink
};
return Ok(resultsModel);
You can't do this. Typescript can only type things based on static analysis at build time, what your describing would require Typescript to know the result of your API call at build time, which it doesn't do.
The best you can do is indicating that your API call can return both of your them:
public myApiFunc(req: MyRequestModel): Observable<any>
But that will still require you to figure out which type returned at runtime.
I was able to find a solution that worked...
getLinksFromSitus(situs: any) {
this.http.post(this.baseUrl + 'getLinksFromSitus', situs).subscribe(data => {
if (data.hasOwnProperty('arcGisLink')) {
this.apiData.next(data);
} else {
let vals = [];
vals = this.apiPropApn.getValue();
const item = vals.concat(data);
this.apiPropApn.next(item);
}
});
}
So, after subscribing to the HttpResponse, I am able to check if the data in the response contains a known property. If it doesn't contain the known property, then it concatenates the data to a BehaviorSubject array. It works perfectly.

Dynamic localization in vue-i18n

I would like to update my localization messages in vue-i18n dynamically.
I am building a webshop, where every item has descriptions in more languages. So what I’d like to achieve is when I get the webshop items from the REST API I want to put their names, descriptions etc. to the messages object in vue-i18n so it can work with them. Does the vue-i18n API have something to handle that? Also I am getting the data from the server (I get a Promise), so how can I make sure it gets updated in the browser view, when I finally get the response, and add the data to the localization?
What I did was write a mixin, and use it everywhere I need dynamic localization:
export default {
methods: {
$t: function (translate) {
if (typeof translate === 'string') {
return this.$i18n.t(translate)
} else if (translate === void 0) {
return this.$i18n.t('loading')
}
return translate[this.$i18n.locale]
}
}
}
This way when my texts look like the following, I can call $t(text) (NOT $t('text') of course):
data: function () {
return {text: {en:'Book', de:'Buch', hu:'Könyv'}}
}
So in your components you have to import this and add it as a mixin:
import dynamicLocalization from '#/components/mixins/dynamic-localization'
export default {
...
mixins:[dynamicLocalization]
...
}

Vue.js: How to pass in data that isn't a parent / access vue methods?

I'm working on a simple timer app. I'm getting 3 pieces of data from the server: timers, projects and users. I believe I'm looping through timers correctly, but I'm not sure if I should be passing in data this way. I want different parts of my app to use the same dataset for users and projects in case a project name changes for example. Here's the code so far with questions embedded. I would like to do a single call for now for all the data at once.
<script>
Vue.component('sidebar-timer', {
props: ['timer','projects','users'],
computed: {
/***** SHOULD PROJECT AND USER BE SET A DIFFERENT WAY? *****/
project: function () {
return this.projects[this.timer.project_id.toString()];
},
user: function () {
return this.users[this.timer.user_id.toString()];
}
},
template: '<li class="project-item"><div class="timer-proj-name"> #{{ project.name }}</div><div class="timer-name"> #{{ user.name }}</div> <button class="timer-start-btn">Start</button><div class="timer-duration">#{{ timer.duration }}</div><div class="timer-status">#{{ timer.status }}</div><div id="toggle-timer-notes"><div class="timer-task"> #{{ timer.notes }}</div><div>timer id: #{{ timer.id }}<input :value="timer.id"></li></div>',
})
var TimerSidebar = Vue.extend({
methods: {
updateData: function () { // GET DATA FROM THE SERVER
var self = this;
$.get('/timers/getJson', function(response){
var userObj = response.users;
var projectObj = response.projects;
var timerObj = response.timers;
var timerArr = Object.keys(timerObj).map(function (key) {return timerObj[key]; });
/***** IS THERE A WAY TO SET projects AND users AT A LEVEL OUTSIDE OF TimerSidebar? *****/
self.$set(self, 'users', userObj);
self.$set(self, 'projects', projectObj);
self.$set(self, 'timers', timerArr);
})
}
}
})
var timerSidebar = new TimerSidebar({
el: '#timer-sidebar',
data: {
timers: [],
projects: [],
users: []
},
})
methods: {
/***** HOW TO ONCLICK CALL updateTimers FROM OUTSIDE THE COMPONENT? *****/
updateTimers: function(){ // ADD TIME RECORD FROM CLICK EVENT
var newTimers = this.timers;
newTimers.push({id: 166, project_id: 123, user_id: 1});
newTimers.sort(function(timer1, timer2){
if(timer1.id > timer2.id){
return 1;
} else if(timer1.id < timer2.id){
return -1;
} else {
return 0;
}
});
this.timers = newTimers;
}
}
This is the standard case when you should be going for a centralised state management. As you have data which is going to be used by multiple components, If the data flow is just limited to one way: parent to child, it can be manageable, but as soon as you get the requirement of updating the parent data when child changes it, or worse, updating the sibling data when another sibling changes it, it becomes messy.
Vue provides it own Flux like implementation, but the general practice is to go with vuex. With this, you store all your projects/users etc in vuex state, and each component can read/update from the central state. If its changed by one component, updated version is available to all components reactively. You can initiate the data in one place using actions in vuex itself.
Following is the architecture diagram:
You can have a look at my answer here on similar question and have a look at example on how to call api and save data in store.

Kendo UI (MVC) Grid AJAX binding form data not sent

Does anybody know what the "Data" part of the Grid Ajax Read fluent API does.
The reason I ask is because my set up is like this:
// razor setup
.Kendo()
.Grid<MyModel>()
.Name("KENDO_UI_GRID")
.DataSource(d =>
d.Ajax()
.Read(r => r
.Data("k_get_datafromform")
.Action("ResultsJson", "ControllerName")
)
.Events(e => e.RequestEnd("k_grid_requestend"))
.Events(e => e.Error("k_grid_error"))
.PageSize(Model.MaxItemsPerPage))
.Columns(// etc etc
// javascript function
function k_get_datafromform() {
var theFormFound = jQuery(".search-form:first");
if (theFormFound) {
// custom helper to convert form to object
return theFormFound.serializeObject();
};
return null;
}
But when the grid POSTs to get the results, it doesn't send the data along with it. The form collection contains the usual Kendo stuff (pagesize etc) but nothing else. What am I doing wrong???
From Telerik:
"This is a known issue in the first service pack release(2013.3.1316) that is already fixed. The additional data for the read request was not included in the serialized request data and was not sent to the server. Please update the version that you are using to the latest service pack(2013.3.1324) which is available for download from your account. I am sorry for the inconvenience caused."
And that's that.
You are using the Data function to send addtional parameters to the server, when the dataSource is performing the operation - in your case the Read operation.
So if you return from the function something like {foo :42}. This parameter equal to 42 will be send to the server.
In your case I assume that the result from the serializeObject is not right.
Can you try to see how you object looks like and share it with us?
You can use
alert(kendo.stringify(theFormFound.serializeObject()));
or
console.log(kendo.stringify(theFormFound.serializeObject())
to investigate
For example, here is a DropdownList (left stuff out to be more clear) that requires additionalData, you'll notice the javascript function "OnAdditionalData" in the .data tag
#(Html.Kendo().DropDownListFor(x => x.FromOpportunity)
.Name("OpportunityDDL")
.DataSource(source => {
source.Read(read =>
{
read.Action("SomeMethod", "SomeController")
.Data("OnAdditionalData");
})
)
and The JS
function OnAdditionalData() {
var Item = 3
return {
partyItem: Item
};
}
So when the data is read it says ok, go to SomeMethod in SomeController and read the Data, but says wait! i need data, what am I bringing to the party. It looks at the JS function and says ok I have a partyItem with a value of 3.
public JsonResult SomeMethod(int partyItem)
{
// partyItem will == 3
}
Notice "partyItem" in the controller is the same name as "partyItem" in the function, they must be the same. Be aware that if you expected a string in the Controller it wouldn't work. if it was var Item = "3" then it would work.

Resources