I am developing an app to store contact information and utilizing Vuejs and Laravel to do it. I am also using the axios library for CRUD functionality.
I have this error on axios.delete() I cannot figure out. This is my Contacts.Vue file:
<script>
export default {
data: function(){
return {
edit:false,
list:[],
contact:{
id:'',
name:'',
email:'',
phone:''
}
}
},
mounted: function(){
console.log('Contacts Component Loaded...');
this.fetchContactList();
},
methods: {
fetchContactList: function(){
console.log('Fetching contacts...');
axios.get('api/contacts').then((response) => {
console.log(response.data);
this.list = response.data;
}).catch((error) => {
console.log(error);
});
},
createContact: function(){
console.log('Creating contact...');
let self = this;
// merging params to the current object
let params = Object.assign({}, self.contact);
// pass above to axios request
axios.post('api/contact/store', params)
.then(function(){
self.contact.name = '';
self.contact.email = '';
self.contact.phone = '';
self.edit = false;
self.fetchContactList();
})
.catch(function(error){
console.log(error);
});
},
showContact: function(id){
let self = this;
axios.get('api/contact/' + id)
.then(function(response){
self.contact.id = response.data.id;
self.contact.name = response.data.name;
self.contact.email = response.data.email;
self.contact.phone = response.data.phone;
})
self.edit = true;
},
updateContact: function(id){
console.log('Updating contact '+id+'...');
let self = this;
// merging params to the current object
let params = Object.assign({}, self.contact);
// pass above to axios request
axios.patch('api/contact/'+id, params)
.then(function(){
self.contact.name = '';
self.contact.email = '';
self.contact.phone = '';
self.edit = false;
self.fetchContactList();
})
.catch(function(error){
console.log(error);
});
},
deleteContact: function(id){
axios.delete('api/contact/'+id)
.then(function(response){
self.fetchContactList();
})
.catch(function(error){
console.log(error);
});
}
}
}
</script>
I am getting a TypeError message saying that self.fetchContactList is not a function.
I know that its saying that the value is not actually a function. There is no typo in the function name. Did I call the function on the wrong object? Should I be using a different property name?
I used self.fetchContactList(); on adding and updating contacts, why will it not work with deleting the contact?
Do I need to add request headers? I didn't have to for the other requests.
If I simply remove self.fetchContactList() it will not function at all.
Despite the error, when I refresh the page, it deletes the contact, but I want the contact deleted upon clicking the delete button.
You don't have let self = this; line in deleteContact function, obviously you would get an error.
alternatively, you can use ES6 arrow functions to avoid assigning this to separate variable like this:
deleteContact: function(id) {
axios.delete('api/contact/'+id)
.then((response) => {
this.fetchContactList();
})
.catch((error) => {
console.log(error);
});
}
Related
I'm trying to retrieve a global session value and set it to the vue variable. The problem is, the id variable is not displaying any value on the console but does display the value on the vue component. I've checked with the vue devtools and the id does contain the correct value.
Vue Component
<template>
<div class="container">
<h1>{{id}}</h1> // the id does displays the value
</div>
</template>
<script>
export default {
data () {
return {
id:'',
}
},
created(){
axios.get('api/studentlecture').then(response => this.id = response.data).catch(function(error){console.log(error)
});
console.log(this.id)
},
methods:{
},
mounted() {
console.log('Component mounted.')
}
}
Controller
public function index()
{
$id= session('userID');
return json_encode($id);
}
Because the axios call is asynchronous. The JavaScript engine will execute the axios request, and while it is waiting it will continue executing the code.
You are trying to log this.id while it has not yet been assigned. If you want to log the value, you have to put it in the callback of your axios function.
axios.get('api/studentlecture')
.then(response => {
this.id = response.data;
console.log(this.id); // <== Here
})
.catch(function(error){console.log(error)});
This happens because console.log(this.id) is executed before axios.get() could resolve it's promise.
There are a few solution for this.
First one is to move console.log() inside then().
created() {
axios.get('api/studentlecture').then(response => {
this.id = response.data;
console.log(this.id);
}).catch(error => {
console.log(error)
});
}
Or you can make use of async/await to wait the promise to resolve
async created() {
try {
// This will wait until promise resolve
const response = await axios.get('api/studentlecture');
this.id = response.data;
console.log(this.id);
} catch(error) {
console.log(error)
}
}
You can learn more about promise here
And more about async/await difference with promise here
You can try using the following code below:
/*FRONT-END VUE*/
this.axios.get("https://localhost:8000/api/v1/data").then((response)=>{
this.data=response.data;
console.log(this.data);
if(this.data.success){
}
});
/*BACK-END LARAVEL*/
function getData(){
$result = array('success'=>true,'data'=>$data);
return Response()->json($result);
}
Hi I've got this app which can connect to an API.
Only problem is it can only get API requests from an PHP file.
I want to change the code so that it wil accept .json API files
Factory
factory.readProducts = function(){
return $http({
method: 'GET',
url: 'https://jsonplaceholder.typicode.com/todos'
});
console.log(factory.readProducts)
};
Currently my GET method should be presumably be changed to fetch
Controller
$scope.readProducts = function(){
// use products factory
productsFactory.readProducts().then(function successCallback(response){
$scope.todos = response.data.records;
console.log($scope.products)
}, function errorCallback(response){
$scope.showToast("Unable to read record.");
});
}
JSON method
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => console.log(json))
according to JSONPlaceholder it's the basic way to acces an JSON API
Needed to change the controller from:
$scope.readProducts = function(){
// use products factory
productsFactory.readProducts().then(function successCallback(response){
$scope.todos = response.data.records;
console.log($scope.products)
}, function errorCallback(response){
$scope.showToast("Unable to read record.");
});
}
To :
$scope.readProducts = function(){
// use products factory
productsFactory.readProducts().then(function successCallback(response){
$scope.todos = response.data.records;
console.log($scope.products)
}, function errorCallback(response){
$scope.showToast("Unable to read record.");
});
}
The $scope.todos = response.data.records needed to be changed to $scope.todos = response.data because of the structure of the API. It had noting to do with the file being JSON or PHP
i am trying to create a service for angular which should get the data from a php that generates a json. Right now my service looks like this
fixEvents.service('contactService', function($http, $q) {
this.getallContact = function() {
var json = $q.defer();
$http.get('models/contact.getall.json')
.success(function(data) {
json.resolve(data);
})
.error(function() {
json.reject();
});
return json.promise;
};
});
and my controller looks like this
fixEvents.controller('contactCtrl', function($scope, contactService) {
$scope.title = "CONTACT";
$scope.jsonContact = contactService.getallContact();
$scope.showMessage = function() {
alert($scope.jsonContact.length);
}
});
the problem is my jsonContact does not get any result. It seems to be undefined. Is there something i did wrong? And by the way is there a better way to do this ? Thank you, Daniel!
You have to use .then back in the controller to work with the data:
var jsonContactPromise = contactService.getallContact();
jsonContactPromise.then(function(data) {
$scope.jsonContact = data
}, function(error) {
console.log("ERROR: " + error);
});
I have to code:
window.TicketCollection = Backbone.Collection.extend({
model:Tickets,
url:"/index.php/tickets/viewJSON"
});
window.TicketsView = Backbone.View.extend({
tagName:'div',
initialize: function () {
this.model.bind("reset", this.render, this);
},
render:function(eventName){
_.each(this.model.models, function(ticket){
$(this.el).append(new TicketListItemView({model:ticket}).render().el);
},this);
return this;
}
});
window.TicketListView = Backbone.View.extend({
tagName: "li",
template:_.template($('#tickets-list-item').html()),
render:function (eventName){
$(this.el).html(this.template(this.model.toJSON));
return this;
}
});
var AppRouter = Backbone.Router.extend({
routes:{
"":"list"
},
list:function(){
window.alert("alright");
this.ticketList = new TicketCollection();
this.ticketLists = this.ticketList.get();
this.ticketListView = new TicketListView({model:this.ticketList});
$("#ticketListHolder").html(this.ticketListView.render().el);
},
});
var app = new AppRouter();
Backbone.history.start();
});
My php is as follows:
<?php header('Content-type: application/json');
echo json_encode(array("ticketID"=>"test", "ticketName"=>"1"));?>
The response from the php is:
[{"ticketID":"1","ticketName":"Fix the admin system"}]
HTML:
<div id="ticketListHolder">
#
</div>
<script type="text/template" id="tickets-list-item">
<div class="supTicket ticketHolder nobg">
<div class="issueType">
<span class="issueInfo"><%= ticketName %></span>
<span class="issueNum">[ #<%= ticketID %>] - <%= fullName %></span>
</div>
</div>
</script>
I get the error: Uncaught ReferenceError: ticketName is not defined, it appears that it's not parsing the json, instead reading it as one string block. Why is this error occuring, when my JSON is returning the correct data.
You don't use collection.fetch anywhere. Your router probably should look like this
var AppRouter = Backbone.Router.extend({
routes:{
"":"list"
},
list:function(){
window.alert("alright");
this.ticketList = new TicketCollection();
this.ticketListView = new TicketListView({
model:this.ticketList,
el:$("#ticketListHolder") // I directly assigned #ticketListHolder as the el
});
this.ticketList.fetch();
},
});
And a Fiddle with a mostly working version of your code http://jsfiddle.net/Cc9Ad/2/
Some points you should check:
your ListView and your ItemView were the other way round,
as Daniel Aranda said in his answer, try to use collections and models for their intended purpose,
this.model.toJSON should have been this.model.toJSON()
set defaults on your models, fullName is not defined and would break the templating engine if used in this state
The revised code
window.Tickets=Backbone.Model.extend({
defaults: {
fullName :"No full name"
}
});
window.TicketCollection = Backbone.Collection.extend({
model:Tickets,
url:"/index.php/tickets/viewJSON"
});
window.TicketsView = Backbone.View.extend({
tagName:'li',
template:_.template($('#tickets-list-item').html()),
initialize: function () {
},
render:function(eventName){
console.log
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
window.TicketListView = Backbone.View.extend({
initialize: function () {
this.collection.bind("reset", this.render, this);
},
render:function (){
this.collection.each( function(ticket){
$(this.el).append(new TicketsView({model:ticket}).render().el);
},this);
return this;
}
});
var ticketList = new TicketCollection();
var ticketListView = new TicketListView({
collection:ticketList,
el:$("#ticketListHolder")
});
// ticketList.fetch();
ticketList.reset([
{"ticketID":"1","ticketName":"Fix the admin system"},
{"ticketID":"2","ticketName":"The ticket 2"}
]);
Model is not the same than collection.
You are trying to use a Collection as a Model.
Check this example:
http://danielarandaochoa.com/backboneexamples/blog/2012/02/22/real-world-usage-of-a-backbone-collection/
Also to fix your specific issue, pass to your template an object instead of a Backbone.Model
$(this.el).html(this.template(this.model.toJSON()));
You was missing the parenthesis.
But as I said, I recommend you to read the article explaining how to use the collections.
I use JSON.parse() function to parse the data sent by the PHP.
var a = $.ajax({
url:"/index.php/tickets/viewJSON",
async:false,
cache:false
}).responseText;
jsonData = JSON.parse(a);
then use _.each to loop jsonData then push each data to your model.
I've been trying for days to get this working and I just cannot figure out why when I have my view to destroy a model which belongs to a collection (which properly has a url attribute for the beginning fetch of models' data), only fires the destroy 'event' which is bubbled up to the collection for easy binding by my list view. But it does not ever send an actual DELETE request or any request to the server at all. Everywhere I look, I see everyone using either the collection's url attr, or urlRoot if the model is not connected to a collection. I've even tested before the actual this.model.destroy() to check the model < console.log(this.model.url());
I have not overwritten the destroy nor sync methods for backbone. Also each model does have an id attribute which is populated via the collection's fetch (from database records).
The destroy takes place in the list item view, and the collection's "destroy" event is bound in the list view. All that works well (the event handling), but the problem, again, is there's no request to the server.
I was hoping that backbone.js would do it automatically. That was what the documentation implies, as well as the numerous examples everywhere.
Much thanks to anyone who can give some useful input.
FYI: I'm developing on wampserver PHP 5.3.4.
ListItemView = BaseView.extend({
tagName: "li",
className: "shipment",
initialize: function (options) {
_.bindAll(this);
this.template = listItemTemplate;
this.templateEmpty = listItemTemplateEmpty;
},
events: {
'click .itemTag' : 'toggleData',
'click select option' : 'chkShipper',
'click .update' : 'update',
'click button.delete' : 'removeItem'
},
// ....
removeItem: function() {
debug.log('remove model');
var id = this.model.id;
debug.log(this.model.url());
var options = {
success: function(model, response) {
debug.log('remove success');
//debug.log(model);
debug.log(response);
// this.unbind();
// this.remove();
},
error: function(model, response) {
debug.log('remove error');
debug.log(response);
}
};
this.model.destroy(options);
//model.trigger('destroy', this.model, this.model.collection, options);
}
});
Collection = Backbone.Collection.extend({
model: Model,
url: '?dispatch=get&src=shipments',
url_put : '?dispatch=set&src=shipments',
name: 'Shipments',
initialize: function () {
_.bindAll(this);
this.deferred = new $.Deferred();
/*
this.fetch({
success: this.fetchSuccess,
error: this.fetchError
});
*/
},
fetchSuccess: function (collection, response) {
collection.deferred.resolve();
debug.log(response);
},
fetchError: function (collection, response) {
collection.deferred.reject();
debug.log(response);
throw new Error(this.name + " fetch failed");
},
save: function() {
var that = this;
var proxy = _.extend( new Backbone.Model(),
{
url: this.url_put,
toJSON: function() {
return that.toJSON();
}
});
var newJSON = proxy.toJSON()
proxy.save(
newJSON,
{
success: that.saveSuccess,
error: that.saveError
}
);
},
saveSuccess: function(model, response) {
debug.log('Save successful');
},
saveError: function(model, response) {
var responseText = response.responseText;
throw new Error(this.name + " save failed");
},
updateModels: function(newData) {
//this.reset(newData);
}
});
ListView = BaseView.extend({
tagName: "ul",
className: "shipments adminList",
_viewPointers: {},
initialize: function() {
_.bindAll(this);
var that = this;
this.collection;
this.collection = new collections.ShipmentModel();
this.collection.bind("add", this.addOne);
this.collection.fetch({
success: this.collection.fetchSuccess,
error: this.collection.fetchError
});
this.collection.bind("change", this.save);
this.collection.bind("add", this.addOne);
//this.collection.bind("remove", this.removeModel);
this.collection.bind("destroy", this.removeModel);
this.collection.bind("reset", this.render);
this.collection.deferred.done(function() {
//that.render();
that.options.container.removeClass('hide');
});
debug.log('view pointers');
// debug.log(this._viewPointers['c31']);
// debug.log(this._viewPointers[0]);
},
events: {
},
save: function() {
debug.log('shipments changed');
//this.collection.save();
var that = this;
var proxy = _.extend( new Backbone.Model(),
{
url: that.collection.url_put,
toJSON: function() {
return that.collection.toJSON();
}
});
var newJSON = proxy.toJSON()
proxy.save(
newJSON,
{
success: that.saveSuccess,
error: that.saveError
}
);
},
saveSuccess: function(model, response) {
debug.log('Save successful');
},
saveError: function(model, response) {
var responseText = response.responseText;
throw new Error(this.name + " save failed");
},
addOne: function(model) {
debug.log('added one');
this.renderItem(model);
/*
var view = new SB.Views.TicketSummary({
model: model
});
this._viewPointers[model.cid] = view;
*/
},
removeModel: function(model, response) {
// debug.log(model);
// debug.log('shipment removed from collection');
// remove from server
debug.info('Removing view for ' + model.cid);
debug.info(this._viewPointers[model.cid]);
// this._viewPointers[model.cid].unbind();
// this._viewPointers[model.cid].remove();
debug.info('item removed');
//this.render();
},
add: function() {
var nullModel = new this.collection.model({
"poNum" : null,
"shipper" : null,
"proNum" : null,
"link" : null
});
// var tmpl = emptyItemTmpl;
// debug.log(tmpl);
// this.$el.prepend(tmpl);
this.collection.unshift(nullModel);
this.renderInputItem(nullModel);
},
render: function () {
this.$el.html('');
debug.log('list view render');
var i, len = this.collection.length;
for (i=0; i < len; i++) {
this.renderItem(this.collection.models[i]);
};
$(this.container).find(this.className).remove();
this.$el.prependTo(this.options.container);
return this;
},
renderItem: function (model) {
var item = new listItemView({
"model": model
});
// item.bind('removeItem', this.removeModel);
// this._viewPointers[model.cid] = item;
this._viewPointers[model.cid] = item;
debug.log(this._viewPointers[model.cid]);
item.render().$el.appendTo(this.$el);
},
renderInputItem: function(model) {
var item = new listItemView({
"model": model
});
item.renderEmpty().$el.prependTo(this.$el);
}
});
P.S... Again, there is code that is referenced from elsewhere. But please note: the collection does have a url attribute set. And it does work for the initial fetch as well as when there's a change event fired for saving changes made to the models. But the destroy event in the list-item view, while it does trigger the "destroy" event successfully, it doesn't send the 'DELETE' HTTP request.
Do your models have an ID? If not, the HTTP request won't be sent. –
nikoshr May 14 at 18:03
Thanks so much! Nikoshr's little comment was exactly what I needed. I spent the last 5 hours messing with this. I just had to add an id to the defaults in my model.