How is it possible to use a mock server for JSON REST API and not for a oData service?
I would like to mock http://localhost:8080/api/v1/configs to get a JSON list of all configurations even if I have no backend connection and I am running the app in mock mode.
The following is not working, it returns furthermore the real data and not the mocked data.
mockserver.js:
sap.ui.define([
"sap/ui/core/util/MockServer",
"sap/base/util/UriParameters"
], function (MockServer, UriParameters) {
"use strict";
var oTokenRequest = {
method: "GET",
path: new RegExp("/actuator/info"),
response: function (oXhr, sNodeId) {
jQuery.sap.log.debug("Incoming request for X-CSRF Token");
oXhr.respondJSON(200, {
"X-Csrf-Token": "myFakeToken"
}, {});
}
};
var oMockServer;
return {
init: function () {
var oUriParameters = new UriParameters(window.location.href);
// configure mock server with a delay
MockServer.config({
autoRespond: true,
autoRespondAfter: oUriParameters.get("serverDelay") || 500
});
var oAllConfigurations = {
method: "GET",
path: "/configs", // or "new RegExp(".*?")" for everything after v1/?
response: function (oXhr, sUrlParams) {
oXhr.respondJSON(200, {}, JSON.stringify({
"uuid": "50df30x9-762b-341c-9881-7315l242b6c5",
"name": "Config1",
"description": "Mapping for component1",
"fileVersion": 3,
"createdAt": 1581517043000,
"updatedAt": 1589039157000
}, {
"uuid": "4f68da04-28a2-4a4e-947k-6d7be70cr03k",
"name": "MOCKSERVER-Config2",
"description": "Mapping for component2",
"fileVersion": 12,
"createdAt": 1553685823000,
"updatedAt": 1589363607000
}, {
"uuid": "6g6chg1-23a2-4a3o-332a-2a6be08ca02f",
"name": "Config3",
"description": "Mapping for component3",
"fileVersion": 1,
"createdAt": 1596119686000,
"updatedAt": 1596119686000
}));
}
};
var aRequests = [oTokenRequest];
aRequests = aRequests.concat(oAllConfigurations);
// create
this.oMockServer = new MockServer({
rootUri: "http://localhost:8080/api/v1",
requests: [oAllConfigurations]
});
// start
this.oMockServer.start();
}
};
});
data-sap-ui-oninit in mockServer.html leads to initMockServer.js
initMockServer.js:
sap.ui.define([
"../localService/mockserver"
], function (mockserver) {
"use strict";
// initialize the mock server
mockserver.init();
// initialize the embedded component on the HTML page
sap.ui.require(["sap/ui/core/ComponentSupport"]);
});
Main.controller.js:
//...
_getConfigList: function () {
var oModelConfigList = new JSONModel();
this.request = new BaseRequests();
return fetch("http://localhost:8080/api/v1/configs")
.then((response) => {
if (response.ok) {
return response.json();
} else {
MessageToast.show(response.statusText);
return null;
}
}).then(json => {
if (json) {
oModelConfigList.setData(json);
this.getView().setModel(oModelConfigList, "ConfigList");
}
});
},
//...
The UI5-Mockserver is only for the UI5 V2-Model implementation. Hence you need to build your own.
To keep it as simple as possible; i would suggest to pack everything in a delegate and use a global flag to toggle mock/real requests during runtime.
//
// your delegate
//
sap.ui.define([
"sap/ui/base/Object"
], function (BaseObject) {
"use strict";
const mockData = {
"uuid": "50df30x9-762b-341c-9881-7315l242b6c5",
"name": "Config1",
"description": "Mapping for component1",
"fileVersion": 3,
"createdAt": 1581517043000,
"updatedAt": 1589039157000
}, {
"uuid": "4f68da04-28a2-4a4e-947k-6d7be70cr03k",
"name": "MOCKSERVER-Config2",
"description": "Mapping for component2",
"fileVersion": 12,
"createdAt": 1553685823000,
"updatedAt": 1589363607000
}, {
"uuid": "6g6chg1-23a2-4a3o-332a-2a6be08ca02f",
"name": "Config3",
"description": "Mapping for component3",
"fileVersion": 1,
"createdAt": 1596119686000,
"updatedAt": 1596119686000
}
return BaseObject.extend("my.namespace.delegate.config", {
read: function(){
if(!window.MY_NAME_SPACE_MOCK){
return fetch("api/v1/configs")
.then((response) => {
if (response.ok) {
return response.json();
} else {
//MessageToast.show(response.statusText);
return null;
}
})
}else{
return new Promise((resolve, reject) => {
let wait = setTimeout(() => {
clearTimout(wait);
resolve(mockData);
}, 2000)
})
}
},
});
});
// usage
sap.ui.define([
"my/namespace/delegate/config"
], function (Config) {
onInit: function() {
this._config = new Config();
this._config.read()
.then((data)=>{
console.log("data can be mock or real depending on MY_NAME_SPACE_MOCK")})
},
})
//
// switch on/off mocking anywhere
//
window.MY_NAME_SPACE_MOCK = true;
delete window.MY_NAME_SPACE_MOCK
FYI: domain("localhost") is not part of a normal AJAX request. Once it is deployed; this will not work anymore
Related
i need to fire/analytics code a pageLoad event whenever a user navigate to different page in the pagination. i
// pageLoad.js
export const PageLoad = () => {
const URL = lowerCaseElement(window.location.href);
const pageLoadObject = {
event: "pageLoad",
page: {
URL,
},
user: {
email: loginInfo?.email || null,
loginStatus: loginInfo ? 'loggedin' : 'anonymous',
}
}
console.log(pageLoadObject);
{
"event": "pageLoad",
"page": {
"URL": "http://localhost:4502/content/my-account/my-list.html?page=2",
},
"user": {
"loginType": "loggedin",
"email": "kiranxxxxxx#gmail.com",
}
}
window.adobeDataLayer.push(pageLoadObject);
}
// pagination.js
import { paginationPageLoad } from '../PageLoad'
const Pagination = (props) => {
useEffect(() => {
paginationPageLoad();
}, [currentPage]);
}
the currentPage is state which consists of page number, i need to fire the adobe.datalayer.push everytime the user navigates between pages. apparently is not working as excepted the event is not firing.
console.log("pageLoad", window.adobeDataLayer.find(
(activity) => activity.event === 'pageLoad'
));
{
"event": "pageLoad",
"page": {
"URL": "http://localhost:4502/content/my-account/my-list.html?page=1",
},
"user": {
"loginType": "loggedin",
"email": "kiranxxxxxxx4#gmail.com",
}
}
when i watch the event the pageLoad event is same when the component renders. like for every navigation the url must be changing but it is same.
I implemented a function calling a REST API. I defined my query, header, parameters.
I wasn't able to manage pagination with loadData() method. How can I achieve my second call to get the page 2 for example ? I tried the recursive way but it didn't work.
Here is an response example of HTTP GET request to REST API:
{
"data": [
{
...
}
],
"pageSize": 1000,
"currentPage": 1,
"lastPage": 3,
"totalObjectCount": 2789,
"truncated": false
}
The function I implemented :
readRestAPI: function (sQuery) {
var oDataModel = new JSONModel();
oDataModel.setSizeLimit(2000);
var oAuthModel = this.getOwnerComponent().getModel("AuthToken");
var oUserModel = this.getOwnerComponent().getModel("User");
var sCompanyName = oUserModel.getData().User[0].userCompanyName;
var sAccountName = oAuthModel.getData().accountName;
var sToken = oAuthModel.getData().token;
var iPage = 1;
var iPageSize = 1000; // Max object for one page in Query API is 1000
var mParams = {
"account": sAccountName,
"company": sCompanyName,
"query": sQuery,
"page": iPage,
"pageSize": iPageSize
};
var sURLQueryAPI = "/API/query/v1";
var sType = "GET";
var mHeaders = {
"Authorization": sToken,
"Content-Type": "application/json",
"X-Client-ID": sAccountName,
"X-Client-Version": "1.0.0"
};
return oDataModel.loadData(sURLQueryAPI, $.param(mParams, true), true, sType, false, true, mHeaders).then(
function (resData) {
return oDataModel;
});
}
Could you please explain me how can I handle the pagination ( 1 to 3 for instance )? Thanks
I want to access json data from external file using vue component but I am not able to get any output in web page.The below is my code which I have tried.Can anyone help me out?
The below is Json data that included the models which I want to display on web page
{
"models": [
{
"title": "IRIS",
"project": "ABC",
"category": "SINGLES",
"bedrooms": 3
},
{
"title": "LILAC",
"project": "ABC",
"category": "DOUBLE",
"bedrooms": 4
},
{
"title": "ASTER",
"project": "ABC",
"category": "SINGLES",
"bedrooms": 4
}
]
}
Vue.component('single-model', {
data: function() {
return {
myData: []
}
},
template: `<div v-for="model in myData">
<p>{{model.title}}</p>
<hr>
</div>`,
created: function() {
this.fetchData();
},
methods: {
fetchData: function() {
var url = 'j.json';
axios.get(url)
.then(function(res) {
this.myData = res.data.models;
});
}
}
});
var vm = new Vue({
el: '#app',
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<div id="app">
<single-model></single-model>
</div>
As you might have noticed white running the provided snippet, template can have only one child element, using a v-for on the outermost element will create multiple children.
this in your case is not referring to the vue-component in fetchData function.
methods:{
fetchData() {
var url = '';
axios.get(url)
.then((res) => {
this.myData = res.data;
});
}
},
Try replacing with the above snippet in your code.
this on your code is not referring to your Vue Component.
I think, the easiest way to solve this issue is by creating a new variable to refer to your Vue Component
fetchData: function() {
var url = 'j.json';
var self = this;
axios.get(url)
.then(function(res) {
self.myData = res.data.models;
});
}
Im creating an app to display recommendation results for apps to users but cannot display it on the app.
The error shows
Display property undefined in my Base Controller file
Error Code is getOwnerComponent("myComp").getTargets().display(to) is in appview.controller.js file (controller file)
NOTE :if i use method 1 for the component container , i can initialise router but error is targets undefined as component id is not found.
However if i use method 2 for the component container , i can getOwnerComponent but display undefined as i cannot initialise router.
Any Ideas?
appview.controller.js
handlePressOpenMenu: function(oEvent) {
var oButton = oEvent.getSource();
// create menu only once
if (!this._menu) {
this._menu = sap.ui.xmlfragment("apps.html.fragment.view_menu", this);
this.getView().addDependent(this._menu);
}
var eDock = sap.ui.core.Popup.Dock;
this._menu.open(this._bKeyboard, oButton, eDock.BeginTop, eDock.BeginBottom, oButton);
},
handleMenuItemPress: function(oEvent) {
if (oEvent.getParameter("item").getSubmenu()) {
return;
}
var to = oEvent.getParameter("item").data("to");
if (to) {
this.getOwnerComponent("myComp").getTargets().display(to);
}
},
manifest.json
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"async": true,
"viewPath": "apps.html",
"controlAggregation": "pages",
"controlId": "idAppControl",
"transition": "slide"
},
"routes": [{
"name": "appview",
"pattern": "",
"target": ["appview"]
}],
"targets": {
"appview": {
"clearAggregation": true,
"viewName": "appview"
},
"xsodata.collaborative": {
"clearAggregation": true,
"viewName": "xsodata.collaborative"
},
"xsodata.contentbased": {
"clearAggregation": true,
"viewName": "xsodata.contentbased"
},
"xsjs.apl_recommendation": {
"clearAggregation": true,
"viewName": "xsjs.apl_recommendation"
},
"xsjs.pal_apriori": {
"clearAggregation": true,
"viewName": "xsjs.pal_apriori"
}
}
}
}
}
}
component.js
return UIComponent.extend("apps.html.Component", {
metadata: {
manifest: "json"
},
/**
* The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
* #public
* #override
*/
init: function () {
// call the base component's init function
sap.ui.core.UIComponent.prototype.init.apply(this, arguments);
// set the device model
this.setModel(models.createDeviceModel(), "device");
// initialise router
this.getRouter().initialise();
}
});
});
index.html Method 1
sap.ui.getCore().attachInit(function() {
new sap.m.Shell({
app: new sap.ui.core.ComponentContainer({
id:"myComp",
height : "100%",
name : "movielens.html",
propagateModel:true
}).placeAt("content")
});
index html Method 2
sap.ui.getCore().attachInit(function() {
var oComp = sap.ui.getCore().createComponent({
name:"apps.html",
id:"myComp",
height:"100%",
propagateModel:true
});
new sap.m.Shell({
app: new sap.ui.core.ComponentContainer({
component:oComp
}).placeAt("content")
});
the exepcted result is supposed to be display of recommendation based on user selection.
UPDATE: I've updated my views to show how I resolved this question using information from the accepted answer.
I'd like to update/increment an attribute ('video_views') of my Backbone JS model via a click event from my view. But, as a Backbone rookie, I'm not sure how to accomplish this exactly.
I'd like the 'video_views' attribute to increment by one with the playVideo event (click).
Thanks for the help!
Here is the structure of my JSON from my API:
{
"id": 8,
"name": "Bike to work day",
"slug": "bike-work-day",
"tagline": "A brief tagline about the video.",
"description": "This is a test.",
"created": "2015-02-06T15:22:26.342658Z",
"website": "http://thevariable.com/",
"logo": "http://dev.thevariable.com/media/brands/logos/test_logo.jpeg",
"video": "http://dev.thevariable.com/media/brands/videos/3D463BC3-38B8-4A6F-BE93-3F53E918EC3B-3533-00000118880074BA_1.1.mp4",
"video_thumbnail": "http://dev.thevariable.com/media/brands/video_thumbnails/3D463BC3-38B8-4A6F-BE93-3F53E918EC3B-3533-00000118880074BA_1.1.mp4.jpg",
"links": {
"self": "http://dev.thevariable.com/api/brands/bike-work-day"
},
"status_display": "published",
"video_views": 0
}
Here are my Backbone views:
var TemplateView = Backbone.View.extend({
templateName: '',
initialize: function () {
this.template = _.template($(this.templateName).html());
},
render: function () {
var context = this.getContext(), html = this.template(context);
this.$el.html(html);
},
getContext: function () {
return {};
}
});
var HomePageView = TemplateView.extend({
templateName: '#home-template',
events: {
'click video': 'updateCounter',
'click .video video': 'playVideo',
'click .sound': 'muteVideo',
'click .js-open-card': 'openCard'
},
initialize: function (options) {
var self = this;
TemplateView.prototype.initialize.apply(this, arguments);
app.collections.ready.done(function () {
app.brands.fetch({success: $.proxy(self.render, self)});
});
},
getContext: function () {
return {brands: app.brands || null};
},
updateCounter: function (e) {
var id = $(e.currentTarget).data('id');
var item = self.app.brands.get(id);
var views = item.get('video_views');
var video = this.$('.video video');
// Only update the counter if the video is in play state
if (video.prop('paused')) {
item.save({video_views: views + 1}, {patch: true});
this.render();
}
},
playVideo: function () {
var video = this.$('.video video');
if (video.prop('paused')) {
video[0].play();
} else {
video.get(0).pause();
}
},
muteVideo: function (e) {
e.preventDefault();
var video = this.$el.parent().find('video');
video.prop('muted', !video.prop('muted'));
this.$('.sound').toggleClass('is-muted');
},
openCard: function (e) {
e.preventDefault();
this.$el.toggleClass('is-open');
this.$el.closest('.card-container').toggleClass('is-open');
}
});
And my Backbone models:
var BaseModel = Backbone.Model.extend({
url: function () {
var links = this.get('links'),
url = links && links.self;
if (!url) {
url = Backbone.Model.prototype.url.call(this);
}
return url;
}
});
app.models.Brand = BaseModel.extend({
idAttributemodel: 'slug'
});
var BaseCollection = Backbone.Collection.extend({
parse: function (response) {
this._next = response.next;
this._previous = response.previous;
this._count = response.count;
return response.results || [];
},
getOrFetch: function (id) {
var result = new $.Deferred(),
model = this.get(id);
if (!model) {
model = this.push({id: id});
model.fetch({
success: function (model, response, options) {
result.resolve(model);
},
error: function (model, response, options) {
result.reject(model, response);
}
});
} else {
result.resolve(model);
}
return result;
}
});
app.collections.ready = $.getJSON(app.apiRoot);
app.collections.ready.done(function (data) {
app.collections.Brands = BaseCollection.extend({
model: app.models.Brand,
url: data.brands
});
app.brands = new app.collections.Brands();
});
Just increment that attribute on the model and save it.
var views = model.get('video_views');
model.set({video_views: views + 1});
model.save();