I tried components methods in vue js. My code like this.
const Thread = Vue.component('threadpage', function(resolve) {
$.get('templates/thread.html').done(function(template) {
resolve({
template: template,
data: function() {
return {
data: {
title: "Data Table",
count: this.GetData
}
};
},
methods: {
GetData: function() {
var data = {
username : "newshubid",
data : {
page : 0,
length : 10,
schedule : "desc"
}
};
var args = {"data" : JSON.stringify(data)};
var params = $.param(args);
var url = "http://example-url";
var result;
DoXhr(url, params, function(response){
result = JSON.parse(response).data;
console.log("load 1", result);
});
setTimeout(function () {
console.log("load 2", result);
return result;
}, 1000);
}
},
created: function(){
this.GetData();
}
});
});
});
But, when I trying to use {{ data.count }} in template. Not showing result what i want. Even I tried return result in GetData.
Whats my problem ? And how to access data from methods ? Please help me, i'm a beginner. Thanks
See the edited code and comments I added below.
You tried to return the result by using return in the function from setTimeout, which won't help you return value from GetData.
Instead, You can just set the value in the callback function of your ajax request.
const Thread = Vue.component('threadpage', function(resolve) {
$.get('templates/thread.html').done(function(template) {
resolve({
template: template,
data: function() {
return {
data: {
title: "Data Table",
// NOTE just set an init value to count, it will be refreshed when the function in "created" invoked.
count: /* this.GetData */ {}
}
};
},
methods: {
GetData: function() {
var data = {
username : "newshubid",
data : {
page : 0,
length : 10,
schedule : "desc"
}
};
var args = {"data" : JSON.stringify(data)};
var params = $.param(args);
var url = "http://example-url";
var result;
var vm = this;
DoXhr(url, params, function(response){
result = JSON.parse(response).data;
// NOTE set data.count to responsed result in callback function directly.
vm.data.count = result;
});
// NOTE I think you don't need code below anymore.
// setTimeout(function () {
// console.log("load 2", result);
// return result;
// }, 1000);
}
},
created: function(){
this.GetData();
}
});
});
});
Related
I have a code, that will make inside the select function an ajax request.
oSelect
.select(function (oEvent) {
return oEvent.getSource();
})
.select(function (oControl) {
let oItem = oControl.getSelectedItem();
let aKeys = oItem.getKey().split("/");
return {plant: aKeys[0], wc: aKeys[1]};
})
.select(function (oSelectedItem) {
let oModel = self.getModel("weightProtocolService");
let oPlantFilter = new Filter("Plant", sap.ui.model.FilterOperator.EQ, oSelectedItem.plant);
let oWcFilter = new Filter("WorkCenter", sap.ui.model.FilterOperator.EQ, oSelectedItem.wc);
oModel.read("/CostCenterCalendarSet", {
success: function (oData, oResponse) {
return Rx.Observable.from(oResponse.data.results);
},
error: function (oError) {
return Rx.Observable.throw(oError);
},
filters: [oPlantFilter, oWcFilter]
});
})
.subscribe(function (oKey) {
console.log(oKey);
},
function (err) {
jQuery.sap.log.fatal(err);
});
My problem here is, that it will subscribe first before the ajax response appears.
How can I solve the problem?
Assuming RxJS 5, replace the last select with a mergeMap and return a new observable:
.mergeMap(function (oSelectedItem) {
let oModel = self.getModel("weightProtocolService");
let oPlantFilter = new Filter("Plant", sap.ui.model.FilterOperator.EQ, oSelectedItem.plant);
let oWcFilter = new Filter("WorkCenter", sap.ui.model.FilterOperator.EQ, oSelectedItem.wc);
return new Observable(observer => {
oModel.read("/CostCenterCalendarSet", {
success: function (oData, oResponse) {
observer.next(oResponse.data.results);
},
error: function (oError) {
observer.error(oError);
},
filters: [oPlantFilter, oWcFilter]
});
});
})
If oModel.read returns a promise, then you can simply do the following:
....
return Observable.fromPromise(oModel.read("/CostCenterCalendarSet", {
filters: [oPlantFilter, oWcFilter]
})
);
If oModel.read does not return a promise, then you would need a custom observable:
....
return Observable.create(function(observer) {
oModel.read("/CostCenterCalendarSet", {
success: function (oData, oResponse) {
return observer.onNext(oResponse.data.results); // or just .next(..) in case you are using rxjs5+
},
error: function (oError) {
return observer.onError(oError); // or just .error(..) in case you are using rxjs5+
},
filters: [oPlantFilter, oWcFilter]
});
});
Kind of lost when iterating over promises, im trying to transform this:
[{
' site' : ['url', 'url', 'url']
},
{
' site' : ['url', 'url', 'url']
}]
so that it becomes:
[{
'site' : [{ 'url' : result_of_function }, { 'url' : result_of_function }, { 'url' : result_of_function }]
},
{
'site' : [{ 'url' : result_of_function }, { 'url' : result_of_function }, { 'url' : result_of_function }]
}]
So far I created the function below, but for some reason checkBranding is not called.
function searchPageArray(brand, siteObjArr) {
return Promise.map(siteObjArr, function(sitesObj){
var k = Object.keys(sitesObj)[0]
var urlArr = sitesObj[k];
return Promise.map(urlArr, function(url){
return searchPage(url).then(function(html){
var tempObj = {}
tempObj[url] = checkBranding(url, html, brand)
return tempObj
})
})
return sitesObj;
})
}
Thanks for the help!
You can use bluebird.js's props() method.
// You must use bluebird to achieve this
var Promise = require('bluebird');
function searchPageArray(brand, siteObjArr) {
return Promise.map(siteObjArr, function (sitesObj) {
var k = Object.keys(sitesObj)[0]
var urlArr = sitesObj[k];
return Promise.map(urlArr, function (url) {
return searchPage(url)
.then(function (html) {
// Use promise.props(). It resolves all properties of a
// object before returning. If there are any properties that
// arent promises they are returned as normal.
return Promise.props({
url: checkBranding(url, html, brand) // Assuming checkBranding() returns a promise.
});
});
});
return sitesObj;
});
}
I'm starting to learn and azure phonejs.
Todo list get through a standard example:
$(function() {
var client = new WindowsAzure.MobileServiceClient('https://zaburrito.azure-mobile.net/', 'key');
var todoItemTable = client.getTable('todoitem');
// Read current data and rebuild UI.
// If you plan to generate complex UIs like this, consider using a JavaScript templating library.
function refreshTodoItems() {
var query = todoItemTable.where({ complete: false });
query.read().then(function(todoItems) {
var listItems = $.map(todoItems, function(item) {
return $('<li>')
.attr('data-todoitem-id', item.id)
.append($('<button class="item-delete">Delete</button>'))
.append($('<input type="checkbox" class="item-complete">').prop('checked', item.complete))
.append($('<div>').append($('<input class="item-text">').val(item.text)));
});
$('#todo-items').empty().append(listItems).toggle(listItems.length > 0);
$('#summary').html('<strong>' + todoItems.length + '</strong> item(s)');
}, handleError);
}
function handleError(error) {
var text = error + (error.request ? ' - ' + error.request.status : '');
$('#errorlog').append($('<li>').text(text));
}
function getTodoItemId(formElement) {
return $(formElement).closest('li').attr('data-todoitem-id');
}
// Handle insert
$('#add-item').submit(function(evt) {
var textbox = $('#new-item-text'),
itemText = textbox.val();
if (itemText !== '') {
todoItemTable.insert({ text: itemText, complete: false }).then(refreshTodoItems, handleError);
}
textbox.val('').focus();
evt.preventDefault();
});
// Handle update
$(document.body).on('change', '.item-text', function() {
var newText = $(this).val();
todoItemTable.update({ id: getTodoItemId(this), text: newText }).then(null, handleError);
});
$(document.body).on('change', '.item-complete', function() {
var isComplete = $(this).prop('checked');
todoItemTable.update({ id: getTodoItemId(this), complete: isComplete }).then(refreshTodoItems, handleError);
});
// Handle delete
$(document.body).on('click', '.item-delete', function () {
todoItemTable.del({ id: getTodoItemId(this) }).then(refreshTodoItems, handleError);
});
// On initial load, start by fetching the current data
refreshTodoItems();
});
and it works!
Changed for the use of phonejs and the program stops working, even mistakes does not issue!
This my View:
<div data-options="dxView : { name: 'home', title: 'Home' } " >
<div class="home-view" data-options="dxContent : { targetPlaceholder: 'content' } " >
<button data-bind="click: incrementClickCounter">Click me</button>
<span data-bind="text: listData"></span>
<div data-bind="dxList:{
dataSource: listData,
itemTemplate:'toDoItemTemplate'}">
<div data-options="dxTemplate:{ name:'toDoItemTemplate' }">
<div style="float:left; width:100%;">
<h1 data-bind="text: name"></h1>
</div>
</div>
</div>
</div>
This my ViewModel:
Application1.home = function (params) {
var client = new WindowsAzure.MobileServiceClient('https://zaburrito.azure-mobile.net/', 'key');
var todoItemTable = client.getTable('todoitem');
var toDoArray = ko.observableArray([
{ name: "111", type: "111" },
{ name: "222", type: "222" }]);
var query = todoItemTable.where({ complete: false });
query.read().then(function (todoItems) {
for (var i = 0; i < todoItems.length; i++) {
toDoArray.push({ name: todoItems[i].text, type: "NEW!" });
}
});
var viewModel = {
listData: toDoArray,
incrementClickCounter: function () {
todoItemTable = client.getTable('todoitem');
toDoArray.push({ name: "Zippy", type: "Unknown" });
}
};
return viewModel;
};
I can easily add items to the list of programs, but from the server list does not come:-(
I am driven to exhaustion and can not solve the problem for 3 days, which is critical for me!
Specify where my mistake! Thank U!
I suggest you use a DevExpress.data.DataSource and a DevExpress.data.CustomStore instead of ko.observableArray.
Application1.home = function (params) {
var client = new WindowsAzure.MobileServiceClient('https://zaburrito.azure-mobile.net/', 'key');
var todoItemTable = client.getTable('todoitem');
var toDoArray = [];
var store = new DevExpress.data.CustomStore({
load: function(loadOptions) {
var d = $.Deferred();
if(toDoArray.length) {
d.resolve(toDoArray);
} else {
todoItemTable
.where({ complete: false })
.read()
.then(function(todoItems) {
for (var i = 0; i < todoItems.length; i++) {
toDoArray.push({ name: todoItems[i].text, type: "NEW!" });
}
d.resolve(toDoArray);
});
}
return d.promise();
},
insert: function(values) {
return toDoArray.push(values) - 1;
},
remove: function(key) {
if (!(key in toDoArray))
throw Error("Unknown key");
toDoArray.splice(key, 1);
},
update: function(key, values) {
if (!(key in toDoArray))
throw Error("Unknown key");
toDoArray[key] = $.extend(true, toDoArray[key], values);
}
});
var source = new DevExpress.data.DataSource(store);
// older version
store.modified.add(function() { source.load(); });
// starting from 14.2:
// store.on("modified", function() { source.load(); });
var viewModel = {
listData: source,
incrementClickCounter: function () {
store.insert({ name: "Zippy", type: "Unknown" });
}
};
return viewModel;
}
You can read more about it here and here.
My service parsing RSS with googleapis and returns a array's Object containing others Objects.
Below, the chrome console ouput :
[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
0: Object
1: Object
2: Object
3: Object
But in my controller cannot use localStorage to retrieve data, the console output return only bracket or nothing :
$scope.feeds = FeedList.get();
window.localStorage.setItem('savedData', JSON.stringify($scope.feeds));
console.log('TEST : ' + window.localStorage['savedData']);
console.log('TEST : ' + JSON.parse(window.localStorage.getItem('savedData')));
console.log('TEST : ' + JSON.parse(window.localStorage['savedData']));
Ouput :
TEST : []
TEST :
TEST :
Please, what is wrong ?
service.js
.factory('FeedLoader', function ($resource) {
return $resource('http://ajax.googleapis.com/ajax/services/feed/load', {}, {
fetch: { method: 'JSONP', params: {v: '1.0', callback: 'JSON_CALLBACK'} }
});
})
.service('FeedList', function ($rootScope, FeedLoader) {
var feeds = [];
this.get = function() {
var feedSources = [
{title: 'rss1', url: 'http://www.website.com/rss/feed/rss_feed_25300'},
{title: 'rss2', url: 'http://www.website.com/rss/feed/rss_feed_10720'},
];
if (feeds.length === 0) {
for (var i=0; i<feedSources.length; i++) {
FeedLoader.fetch({q: feedSources[i].url, num: 10}, {}, function (data) {
var feed = data.responseData.feed;
console.log(feed.entries);
feeds.push(feed.entries);
});
}
}
return feeds;
};
})
What's wrong is that FeedList.get() uses asynchrony and $scope.feeds will not be populated right away.
Try this:
$scope.feeds = FeedList.get();
$scope.feeds.then(function () {
// $scope.feeds is done loading now
window.localStorage.setItem('savedData', JSON.stringify($scope.feeds));
console.log('TEST : ' + window.localStorage['savedData']);
console.log('TEST : ' + JSON.parse(window.localStorage.getItem('savedData')));
console.log('TEST : ' + JSON.parse(window.localStorage['savedData']));
});
Edit: Now that you've provided the code for your service, it's clear that it doesn't return a promise. You need to do that in order for the consumers of your service to be able to wait on the results:
.service('FeedList', function ($rootScope, $q, FeedLoader) {
var feeds;
this.get = function() {
var feedSources = [
{title: 'rss1', url: 'http://www.website.com/rss/feed/rss_feed_25300'},
{title: 'rss2', url: 'http://www.website.com/rss/feed/rss_feed_10720'},
];
if (!feeds) {
var feedPromises = feedSources.map(function (source) {
return FeedLoader.fetch({q: source.url, num: 10}, {}).$promise
.then(function (data) {
return data.responseData.feed.entries;
});
});
feeds = $q.all(feedPromises)
.then(function (retrievedFeeds) {
return Array.prototype.concat([], retrievedFeeds);
});
}
return feeds;
};
})
The problem is that you don't handle async request properly, so:
$scope.feeds = [];
console.log('TEST : Load feeds async');
FeedList.get().then(function () { // each feed comes as argument
angular.forEach(arguments, function (feed) {
$scope.feeds.concat(feed); // merge arrays
});
window.localStorage.setItem('savedData', JSON.stringify($scope.feeds));
console.log('TEST : ' + window.localStorage['savedData']);
console.log('TEST : ' + JSON.parse(window.localStorage.getItem('savedData')));
console.log('TEST : ' + JSON.parse(window.localStorage['savedData']));
});
Service:
.service('FeedList', function ($q, $rootScope, FeedLoader) {
this.get = function () {
var promises = []; // to handle async loading
var feedSources = [{
title: 'rss1',
url: 'http://www.website.com/rss/feed/rss_feed_25300'
}, {
title: 'rss2',
url: 'http://www.website.com/rss/feed/rss_feed_10720'
}];
angular.forEach(feedSources, function (source) {
var defer = $q.defer();
FeedLoader.fetch({
q: source.url,
num: 10
}, {}, function (data) {
var feed = data.responseData.feed;
defer.resolve(feed.entries); // todo - need to handle errors with 'defer.reject'
});
promises.push(defer.promise);
});
return $q.all(promises);
};
})
I've just started using Backbone.js and my test cases are churning up something pretty weird.
In short, what I am experiencing is -- after I call a Backbone Model's constructor, some of the fields in my object seem to come from a previously item. For instance, if I call:
var playlist = new Playlist({
title: playlistTitle,
position: playlists.length,
userId: user.id
});
playlist.get('items').length; //1
however if I do:
var playlist = new Playlist({
title: playlistTitle,
position: playlists.length,
userId: user.id,
items: []
});
playlist.get('items').length; //0
Here's the code:
define(['ytHelper', 'songManager', 'playlistItem'], function (ytHelper, songManager, PlaylistItem) {
'use strict';
var Playlist = Backbone.Model.extend({
defaults: {
id: null,
userId: null,
title: 'New Playlist',
selected: false,
position: 0,
shuffledItems: [],
history: [],
items: []
},
initialize: function () {
//Our playlistItem data was fetched from the server with the playlist. Need to convert the collection to Backbone Model entities.
if (this.get('items').length > 0) {
console.log("Initializing a Playlist object with an item count of:", this.get('items').length);
console.log("items[0]", this.get('items')[0]);
this.set('items', _.map(this.get('items'), function (playlistItemData) {
var returnValue;
//This is a bit more robust. If any items in our playlist weren't Backbone.Models (could be loaded from server data), auto-convert during init.
if (playlistItemData instanceof Backbone.Model) {
returnValue = playlistItemData;
} else {
returnValue = new PlaylistItem(playlistItemData);
}
return returnValue;
}));
//Playlists will remember their length via localStorage w/ their ID.
var savedItemPosition = JSON.parse(localStorage.getItem(this.get('id') + '_selectedItemPosition'));
this.selectItemByPosition(savedItemPosition != null ? parseInt(savedItemPosition) : 0);
var songIds = _.map(this.get('items'), function(item) {
return item.get('songId');
});
songManager.loadSongs(songIds);
this.set('shuffledItems', _.shuffle(this.get('items')));
}
},
//TODO: Reimplemnt using Backbone.sync w/ CRUD operations on backend.
save: function(callback) {
if (this.get('items').length > 0) {
var selectedItem = this.getSelectedItem();
localStorage.setItem(this.get('id') + '_selectedItemPosition', selectedItem.get('position'));
}
var self = this;
console.log("Calling save with:", self);
console.log("my position is:", self.get('position'));
$.ajax({
url: 'http://localhost:61975/Playlist/SavePlaylist',
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(self),
success: function (data) {
console.log('Saving playlist was successful.', data);
self.set('id', data.id);
if (callback) {
callback();
}
},
error: function (error) {
console.error("Saving playlist was unsuccessful", error);
}
});
},
selectItemByPosition: function(position) {
//Deselect the currently selected item, then select the new item to have selected.
var currentlySelected = this.getSelectedItem();
//currentlySelected is not defined for a brand new playlist since we have no items yet selected.
if (currentlySelected != null && currentlySelected.position != position) {
currentlySelected.set('selected', false);
}
var item = this.getItemByPosition(position);
if (item != null && item.position != position) {
item.set('selected', true);
localStorage.setItem(this.get('id') + '_selectedItemPosition', item.get('position'));
}
return item;
},
getItemByPosition: function (position) {
return _.find(this.get('items'), function(item) {
return item.get('position') == position;
});
},
addItem: function (song, selected) {
console.log("this:", this.get('title'));
var playlistId = this.get('id');
var itemCount = this.get('items').length;
var playlistItem = new PlaylistItem({
playlistId: playlistId,
position: itemCount,
videoId: song.videoId,
title: song.title,
relatedVideos: [],
selected: selected || false
});
this.get('items').push(playlistItem);
this.get('shuffledItems').push(playlistItem);
this.set('shuffledItems', _.shuffle(this.get('shuffledItems')));
console.log("this has finished calling");
//Call save to give it an ID from the server before adding to playlist.
songManager.saveSong(song, function (savedSong) {
song.id = savedSong.id;
playlistItem.set('songId', song.id);
console.log("calling save item");
$.ajax({
type: 'POST',
url: 'http://localhost:61975/Playlist/SaveItem',
dataType: 'json',
data: {
id: playlistItem.get('id'),
playlistId: playlistItem.get('playlistId'),
position: playlistItem.get('position'),
songId: playlistItem.get('songId'),
title: playlistItem.get('title'),
videoId: playlistItem.get('videoId')
},
success: function (data) {
playlistItem.set('id', data.id);
},
error: function (error) {
console.error(error);
}
});
});
return playlistItem;
},
addItemByVideoId: function (videoId, callback) {
var self = this;
ytHelper.getVideoInformation(videoId, function (videoInformation) {
var song = songManager.createSong(videoInformation, self.get('id'));
var addedItem = self.addItem(song);
if (callback) {
callback(addedItem);
}
});
},
//Returns the currently selected playlistItem or null if no item was found.
getSelectedItem: function() {
var selectedItem = _.find(this.get('items'), function (item) {
return item.get('selected');
});
return selectedItem;
}
});
return function (config) {
var playlist = new Playlist(config);
playlist.on('change:title', function () {
this.save();
});
return playlist;
};
});
basically I am seeing the property 'items' is populated inside of initialize when I've passed in a config object that does not specify items at all. If I specify a blank items array in my config object, then there are no items in initialize, but this seems counter-intuitive. Am I doing something wrong?
The problem is with using reference types (arrays) in the defaults object. When a new Playlist model is created without specifying an items value, the default is applied. In case of arrays and objects this is problematic, because essentially what happens is:
newModel.items = defaults.items
And so all models initialized this way refer to the same array. To verify this, you can test:
var a = new Playlist();
var b = new Playlist();
var c = new Playlist({items:[]});
//add an item to a
a.get('items').push('over the rainbow');
console.log(b.get('items')); // -> ['over the rainbow'];
console.log(c.get('items')); // -> []
To get around this problem, Backbone supports defining Model.defaults as a function:
var Playlist = Backbone.Model.extend({
defaults: function() {
return {
id: null,
userId: null,
title: 'New Playlist',
selected: false,
position: 0,
shuffledItems: [],
history: [],
items: []
};
}
});