I am creating a website where the backend is node.js with express, and clientside is using mithril. We cannot use ajax, form and jquery.
My question is how can we communicate from mithril js file to express? Let me give you example:
app.post("/testFunction",function(req,res){
//Pass result
});
In mithril:
m.render(document.body, [
m('input[type=text]'),
m('button'),
m('span', 'show the result')
]);
Here I have an input box and a button. When i click on button it should call my function in express, save data and return the message to be displayed in a span.
Any ideas?
You need to use m.request to make a post to your endpoint. Check out the docs here (http://mithril.js.org/request.html). Here's a quick example.
m.render(document.body, [
m('input[type=text]#testInput'),
m('button', {
onclick: function() {
document.getElementById("testInput").value
m.request({
method: "PUT",
url: "http://127.0.0.1:3000/testFunction",
data: {
inputValue: document.getElementById("testInput").value
}
})
.then(function(response) {
console.log(response);
})
}
}, "Send Request")
]);
Related
I have reviewed a few similar posts on here but everything I have found so far is using href to redirect to a totally new webpage.
I have a button in my JavaScript code which uses the Material-UI <Link>
<Button component={Link} to="/ratings" className={classes.addImage} onClick={this.submitScore}>
This button both redirects the webpage and calls a function which initiates a server request. Now this code seemed to be running fine, both redirecting and running its onClick function. However I recently discovered that running my code when not on WiFi often results in my image upload request to be ignored. I've been trouble shooting this for a little while and my current theory is the cell data is slower and the page is rerouting before the upload request gets called.
Although this doesn't quite make sense to me. It seems like the code should either run after the Link is called or not, but what I am seeing is the image upload request work while on WiFi but work infrequently while on cell data.
Any thoughts would be appreciated.
Here is the onClick function if it is helpful:
submitScore = () => {
console.log(this.state)
this.props.dispatch({type: 'SUBMIT_SCORE', payload: {ratings: this.props.scores, user_id : this.props.user.id, name: this.state.beerName, url: this.state.filename, notes: this.state.notes, filename: `${this.props.user.id}_${Date.now()}`}})
// this.props.dispatch({type: 'ADD_PICTURE', payload: {picture: this.state.imgSrc, filename: `${this.props.user.id}_${Date.now()}`}})
axios.get('/picture', {params: {filetype: this.state.imageType, filename: this.state.filename}})
.then(response =>{
var signedUrl = response.data;
console.log(response)
console.log(signedUrl)
var headers= {
'Content-Type': this.state.imageType,
};
console.log(...this.state.imageType)
return axios.put(signedUrl, this.state.newfile, {headers:headers});
})
.then(function (result) {
console.log(result,'success');
})
.catch(function (err) {
console.log(err, 'fail');
});
swal({
title: "Good job!",
text: "You clicked the button!",
icon: "success",
timer: 2000,
});
}
Instead of linking to a new page in your button, can you set it up so you redirect on success?
.then(function (result) {
console.log(result,'success');
window.location.assign('/ratings'); // <-- Redirect here
})
You would need to remove the link from your button.
I have a very simple address application in AngularJS. It connects to an API using $resource.
The ID I use is the mobilephone number of the person (I know it's not the best way to do it, but it's just an sample application to show a 3-tier application setup) So I've 2 pages with the same form:
The problem i'm facing is that it uses the same $resource for saving a new address and saving an edited address. When iḿ saving a new address it has to use the url http://127.0.0.1:5000/api/contacts/ without an id appended on it (the new ID it will get on the api/database side is the filled in mobile phone number)
When I edit an existing address and click the save button it has to use another url; http://127.0.0.1:5000/api/contacts/#mobilePhone.
So i've read the angular documentation on https://docs.angularjs.org/api/ngResource/service/$resource which states that you can override your paramDefaults in your actions. So that is what I try to do using this code:
$resource('http://127.0.0.1:5000/api/contacts/:id',{id:'#mobilePhone'},{
get: {
method: 'GET'
}, update: {
method: 'PUT'
}, save: {
method: 'POST',
id:''
}
},{});
which seems to be correct given the information. It appends the mobilePhone number on every GET and every PUT the get and update method respectively. When it calls the save method it should override the :id with an empty string, but it doesn't do that.
Clearly i'm doing something wrong.
If you need more code snipets let me know, I tried to keep it as clean as possible.
Update:
This is how I call the save method:
....
.controller('MovieCreateController',function($scope,$state,$stateParams,Movie){
$scope.movie=new Movie();
$scope.addMovie=function(){
$scope.movie.$save(function(){
$state.go('movies');
});
}
}
And this is the edit method:
....
.controller('MovieEditController',function($scope,$state,$stateParams,Movie){
$scope.updateMovie=function(){
$scope.movie.$update(function(){
$state.go('movies');
});
};
$scope.loadMovie=function(){
$scope.movie=Movie.get({id:$stateParams.id});
};
$scope.loadMovie();
});
There is not much code in your question, so I'll try to explain what you should do to use $resource.
Have a look at following code:
// The $resource service is a helper to create a 'constructor' function
// Contact below is a function
var Contact = $resource('http://127.0.0.1:5000/api/contact/:id',{id:'#mobilePhone'}, {
get: {
method: 'GET' // You don't need to override the GET
}, update: {
method: 'PUT'
}, save: {
method: 'POST'
}});
// Be sure to create an 'entity' from the Contact $resource
// The 'new' will create a $resource instance with $update, $save methods overridden methods
var contact = new Contact({name: 'foobar'});
contact.$save(); // Will send a POST request
contact.mobilePhone = 2; // This is your id !
contact.$update(); // Will send a PUT request
If your resources always have a RESTful representation, I suggest that you use, as per suggested at angular discussion on issue#9807:
resource.prototype.$save = function() {
if (this.id) {
return this.$update();
} else {
return this.$create();
}
};
..rather that always overriding your $resource methods.
This is how you need to call your save method
$scope.movie=new Movie();
$scope.addMovie=function(){
$scope.movie.$save(function(){
$state.go('movies');
});
}
This is how you need to call your edit method
$scope.movie=new Movie();
$scope.updateMovie=function(){
$scope.movie.$update({ "mobilePhone": $stateParams.id},function(){
$state.go('movies');
});
};
For that you need to create a factory for $resource.which is always recommendable
Try this
.factory('movie', ['$resource', function ($resource) {
return $resource('http://127.0.0.1:5000/api/contacts/:id',{id:'#mobilePhone'},{}, {
update: { method: 'PUT' },
query: {
method: 'GET',
isArray: false
}
})
}])
Inject your factory in your controller
.controller('MovieCreateController',['$scope','$state','$stateParams','movie',function($scope,$state,$stateParams,Movie){
}]);
I'm trying to automate end to end testing with protractor and I'm using sinonjs to setup a fakeServer to respond to certain ajax calls (not all) which are triggered by button clicks.
I'm stuck and not sure how to go about it and being a novice in automation I'm not sure if I'm on the right path.
var sinon = require('sinon');
describe("SinonFakeServerTest", function() {
var fakeServer;
beforeEach(function () {
fakeServer = sinon.fakeServer.create();
fakeServer.autoRespond = true;
var data = {key1: 'xyz', key2: 'abc'};
var response = [ 200, { "Content-Type": "application/json" }, data ];
fakeServer.respondWith( '/abc/xyz/*', response );
}
afterEach(function () {
fakeServer.restore();
}
it("should fake a ajax request", function () {
// click on this button triggers ajax call..
element(by.css('.take-button')).click();
//should show fake data on ui
});
});
This is the production code for button click controller and model
'.take-button click' : function(el, ev) {
model.getData(listParams, this.proxy('setUpData'));
},
getList : function(params, success) {
$.ajax({
url : '/abb/xyz/getAll.htm',
dataType : 'json',
type : "GET",
data : {
params : params
},
success : success
});
}
I didn't successfully fake server with Sinon's fakeServer feature when production code was using JQuery for AJAX calls.
I would suggest to try plain Sinon stubbing for $.ajax. There is actually example on sinonjs.org site (look into section Testing Ajax):
after(function () {
// When the test either fails or passes, restore the original
// jQuery ajax function (Sinon.JS also provides tools to help
// test frameworks automate clean-up like this)
jQuery.ajax.restore();
});
it("makes a GET request for todo items", function () {
sinon.stub(jQuery, "ajax");
getTodos(42, sinon.spy());
assert(jQuery.ajax.calledWithMatch({ url: "/todo/42/items" }));
});
I solved the above issue in protractor without sinonjs.
I used mockjax to hack selected ajax calls and injected this script through browser.executeScript()
Am using kartik growl and i would like to show the growl via ajax success
I have tried
This is the javascript code:
$.post({
url: "forwardpr", // your controller action
dataType: 'json',
data: {keylist: keys,user:userdata},
success: function(data) {
console.log(data);
//$.pjax.reload({container:'#forward-grid'});
$.growl( data.growl );
},
error: function(err){
alert(err);
console.log("server error");
}
});
This is the controller code:
$growl = [
'title' => "Group members updated.<hr>",
'icon' => 'glyphicon glyphicon-ok-sign',
'message' => "Successifully updated.",
'showSeparator' => true,
];
echo json_encode(['response'=>"Successifully forwarded pr(s)", 'growl' => $growl ]);
If you see TypeError: $.growl is not a function, then it means you have not included required files to AppAsset.php file.
To solve this problem, go to assets/AppAsset.php file and add:
public $css = [
// ... Something else might be here
'css/jquery.growl.css',
];
And
public $js = [
// Something else might be here
'js/core.js',
];
Because of missing .js file, you have that error in console (TypeError: $.growl is not a function). But you also must add .css file as well because without it you will not see growl, even though it works.
I believe you're using the wrong function. Here's offical docs:
"Another important update is since version 3.x you no longer call the
plugin using $.growl(...) you must use $.notify(...)."
In another words, just try using $.notify(...) instead of $.growl(...).
I am trying to develop my application in Laravel 4 and Angular JS, my application allows user to retrieve their Information through the system via Text Change.
Angular is used to pass data input from the user to Laravel which in turn retrieves the Information from the Database.
However Laravel is unable to retrieve the data passed from Angular.
View
<div data-ng-controller="ReservationController">
<input id='ERI' type='text' data-ng-model="scanRID" data-ng-change="queryRes()" name='exampleInput' maxlength='3' />
</div>
Angular Factory
app.factory('exampleFactory', function($http) {
var factory = {};
factory.getExample = function(scanRID) {
return $http({
method: 'GET',
url: LARAVEL_CONTROLLER + 'Example',
data: $.param(scanRID)
});
};
return factory;
});
Angular Controller
app.controller('exampleController', function($scope, $http, exampleFactory) {
$scope.queryRes = function() {
if($scope.scanRID.length == 3) {
exampleFactory.getExample($scope.scanRID)
.success(function (data) {
// Do Something Here
})
.error(function (data) {
console.log(data);
});
}
};
});
Laravel 4 Routes
Route::get('Example', 'ExampleController#show');
Laravel 4 ExampleController
class ExampleController extends \BaseController {
public function show()
{
$id = Input::get('scanRID'); // This here might be wrong. It's always empty!
$data = ExampleModel::find($id); // Able to query and retrieve.
return Response::JSON($data); // Returns empty.
}
}
Laravel 4 ExampleModel
class ExampleModel extends Eloquent {
// The id of this table is what I want, but I can't retrieve it.
protected $fillable = ['id', 'ExampleData1', 'ExampleData2'];
protected $table = 'exampleTable';
}
I have searched everywhere for a solution, it seems that everyone is able to successfully make the Ajax call. I think there is something that I am missing out that I am unaware about.
I have also tried setting CSRF Token, but however, I do not think that is an issue. So my last resort is to turn to the experts and hope someone is able to help me.
On a side note, I am fairly new to Laravel and Angular, so if you do post a solution, please explain to me the issue as I would like to learn more about Angular and Laravel.
Thank you for reviewing my issue.
You are not passing the value of scanRID by scanRID parameter instead pass only the value without parameter. So you are try to get the value from scanRID using Input::get('scanRID'); but without having scanRID parameter. that should be the case ur not getting the value :)
return $http({
method: 'GET',
url: LARAVEL_CONTROLLER + 'Example',
data: $.param({scanRID:scanRID}) //Change Here
});
OR
return $http({
method: "GET",
url: LARAVEL_CONTROLLER + 'Example',
params: {scanRID:scanRID} //Change Here
);
change like this