I have this problem when trying to bring the data of a route through AJAX.
I want to make a Dynamic Select that according to the "Faculty" chosen, show the "programs" that belong to that faculty.
this is my route
Route::get('selectprogramas/{id}', 'SyllabusController#getProgramas');
This is the model of Programas
class Programa extends Model
{
protected $table = 'Programas';
protected $fillable = [ 'nombre', 'perfil_profesional', 'competencias', 'facultad_id',
'perfil_profesional'];
public function selectprogramas($id){
return Programa::Where('facultad_id', $id)->get();
}
}
this is the function in the controller
public function getProgramas(Request $request, $id){
if($request->ajax()){
$programas = Programa::selectprogramas($id);
return response()->json($programas);
}
}
these are the two select in the html, I use Laravel Collective
<div class="form-group col-9 font-weight-bold">
{{ Form::label('facultad', 'Facultades:') }}
{{ Form::select('facultad', $facultades, null, ['class' => 'form-control', 'id' => 'facultad']) }}
</div>
<div class="form-group col-9 font-weight-bold">
{{ Form::label('programa', 'Programas:') }}
{!! Form::select('programa', ['placeholder'=>'Selecciona'], null, ['id'=>'programa']) !!}
</div>
and this is my javascript
$("#facultad").change(function (event){
console.log("entre!!");
$.get("../selectprogramas/" + event.target.value + "" ,function(response, facultad){
$("#programa").empty();
for(i=0; i<response.length; i++){
$("#programa").append("<option>"+response[i].nombre+"</option>");
}
});
});
the error I have is this:
already solved!
I made this change in controller function
public function getProgramas(Request $request, $id){
if($request->ajax()){
$programas = Programa::where('facultad_id', $id)->get();
return response()->json($programas);
}
}
Related
I am trying to update view_count column on every #click. but couldn't figure out the right way of it.
First made the controller --resources and fetch datas via api.
controller:
public function index()
{
$articles = Article::all();
return response()->json([
"articles" => $articles
], 200);
}
public function show($id)
{
$article = Article::whereId($id)->first();
return response()->json([
"article" => $article
], 200);
}
also set the update function too.
public function update(Request $request, $id)
{
$view = Article::find($id);
$view->update($request->where("view_count"));
return response()->json(["message" => "view_count updated"]);
}
I set the api routes:
Route::get('/articles', 'ArticlesController#index');
Route::get('/articles/{id}', 'ArticlesController#show');
Route::get('/articles/{id}', 'ArticlesController#update');
And finally in Vue.js
<p class="button">
<i #click.prevent="count" class="fas fa-chevron-right"></i>
</p>
data(){
return {
view: 0,
};
},
methods: {
count: function(){
axios.post("/api/articles" + this.item.id).then(response => {
this.view++;
})
window.location.href = "pages/" + this.item.id
}
}
it's counting but not update the col. also, when I refresh the page of course it will start to count from 0... it's not really efficient way to it. what is the best and right way to do it?
Thank you.
Not: By the way I am fetching and iterating api in the parent component:
<div class="listWrap" :key="item.id" v-for="item in filterArticles">
<list :item="item" />
</div>
your workflow to update views is wrong.
first, we should change our uri method of the update method to GET like below :
Route::get('/articles/update/{id}', 'ArticlesController#update');
then, our update method within ArticlesController to increment view_count value:
public function update(int $id)
{
// i have changed the $view by $article
$article = Article::find($id);
$article->view_count++;
$article->save();
return response()->json(["message" => "view_count updated", 201]);
}
and within our Vue component, we should update the URI of the update method and the HTTP method name because we should use the same HTTP verb in both client and server sides.
<p class="button">
<i #click.prevent="count" class="fas fa-chevron-right"></i>
</p>
<script>
export default {
// as you are using parent/child relationship betwen components, you should use props.
props: { item: Object },
data(){
return {
view: 0,
};
},
methods: {
count: function(){
axios.get(`/api/articles/update/${this.item.id}`).then(response => {
this.view++;
})
window.location.href = "pages/" + this.item.id;
}
}
}
</script>
When clicking a button I am calling a web api with ajax. My form is using JqueryVal, to make form validations, according to my viewmodel data annotations.
My problem is that when I click the button "Listo" in my form, it calls my API, inspite of jqueryval is marking an error( selecting a file is required)
This is my code:
My viewmodel that contains data annotations(the dataannotations are used along with the jquery.validate.js and jquery.validate.unobtrusive.js. As you can see, it is working, but is not preventing the API from being called):
public class CursoViewModel
{
public Guid Id { get; set; }
[MaxLength(125)]
public string Titulo { get; set; }
[Required]
public string Descripcion { get; set; }
[Required(ErrorMessage ="selecciona una imagen para tu curso")]
[DataType(DataType.Upload)]
public HttpPostedFileBase Imagen { get; set; }
}
The class posted to my api
public class person
{
public string name { get; set; }
public string surname { get; set; }
}
The Api code
[HttpPut]
[Route("api/ProfesorCurso/test")]
public string Put(person p)
{
return p.name + p.surname;
}
My View
#model project.ViewModels.CourseViewModel
<form id="Editcurso" method="post" action="#">
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "Please fix the following errors.")
<div class="container">
<div class="form-group">
#Html.LabelFor(c=>c.Titulo)
#Html.TextBoxFor(c => c.Titulo, new {id="titulo", #class="form-control"})
#Html.ValidationMessageFor(m => m.Titulo)
</div>
<div class="form-group">
#Html.LabelFor(c => c.Descripcion)
#Html.TextAreaFor(c => c.Descripcion, new {id="descripcion", #class = "form-control" })
#Html.ValidationMessageFor(m => m.Descripcion)
</div>
<div class="thumbnail" id="imagencurso"></div>
<div class="form-group">
#Html.LabelFor(m => m.Imagen)
#Html.TextBoxFor(m => m.Imagen, new {id="imagen" ,type = "file", data_rule_validCustomer = "true" })
#Html.ValidationMessageFor(m => m.Imagen)
</div>
<button id="submiter" type="submit" class="btn btn-primary">Listo!</button>
</div>
</form>
The scripts in the view
#section scripts
{
#Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function () {
$("#submiter").click(function () {
jQuery.support.cors = true;
var person = new Object();
person.name = "Sourav";
person.surname = "Kayal";
$.ajax({
url: '/api/ProfesorCurso/test',
type: 'PUT',
dataType: 'json',
data: person,
success: function (data) {
console.log(data);
return false;
},
error: function (x, y, z) {
alert('error al postear');
return false;
}
});
});
});
</script>
}
What can I do to prevent ajax to call my api when clicking my form button, if there are Jquery validation errors?
thanks
You should be handling the .submit() event of the form, and then your can check .valid(), and if not cancel the ajax call. Note you should also be cancelling the default submit.
$('#Editcurso').submit(e) {
e.preventDefault(); // prevent the default submit
if (!$(this).valid()) {
return; // exit the function and display the errors
}
....
$.ajax({
....
});
}
As a side note, there is no point adding new { id="titulo" } etc - the HtmlHelper methods that generate form controls already add an id attribute based on the property name
I am using laravel 5.4 and Vue.js 2 to save some information along with file(video) in DB.But i got error like this
error: http://imgur.com/a/7XGERPUT
http://localhost:8000/videos/null 404 (Not Found)
Uncaught (in promise) TypeError: Cannot read property 'uid' of undefined
NotFoundHttpException in Handler.php line 131:
No query results for model [App\Models\Video].
Route:
Route::group(['middleware'=>['auth']],function(){
Route::get('/upload','VideoUploadController#index');
Route::post('/videos','VideoController#store');
Route::put('/videos/{video}','VideoController#update');
Route::get('/channel/{channel}/edit','ChannelSettingsController#edit');
Route::put('/channel/{channel}/edit','ChannelSettingsController#update');
});
Controler:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\VideoUpdateRequest;
use App\Models\Video;
class VideoController extends Controller
{
public function store(Request $request)
{
$uid = uniqid(true);
$channel = $request->user()->channel()->first();
$video = $channel->video()->create([
'uid'=>$uid,
'title'=>$request->title,
'description'=>$request->description,
'visibility'=>$request->visibility,
'video_filename'=>"{$uid}.{$request->extension}",
]);
return response()->json([
'data' => [
'uid' => $uid
]
]);
}
public function update(VideoUpdateRequest $request, Video $video)
{
//authentication checked here .......
$video->update([
'title' => $request->title,
'description' => $request->description,
'visibility' => $request->visibility,
'allow_votes' => $request->has('allow_votes'),
'allow_comments' => $request->has('allow_comments')
]);
if ($request->ajax()) {
return response()->json(null, 200);
}
return redirect()->back();
}
}
Uplod.vue
<template>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Example Component</div>
<div class="panel-body">
<input type="file" name="video" id="video" #change="changfileInputChange" v-if="!uploading">
<div id="video-form" v-if="uploading&&!failed">
<div class="form-group">
<label for="title">Title</label>
<input type="" name="" v-model="title" class="form-control">
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea class="form-control"v-model="description"></textarea>
</div>
<div class="form-group">
<label for="visibility">Visibility</label>
<select class="form-control" v-model="visibility">
<option value="private">Private</option>
<option value="public">Public</option>
<option value="unlisted">Unlisted</option>
</select>
</div>
<span class="help-block pull-right">{{saveStatus}}</span>
<button class="btn btn-default" type="submit"#click.prevent="update">Save changes</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
data()
{
return{
uid:null,
uploading:false,
uplodComplete:false,
failed:false,
title:'unlisted',
description:null,
visibility:'private',
saveStatus:null
}
},
methods:{
changfileInputChange()
{
this.uploading=true;
this.failed=false;
this.file=document.getElementById('video').files[0];
this.storeVideo().then(()=>{
})
},
storeVideo(){
return this.$http.post('/videos',{
title:this.title,
description:this.description,
visibility:this.visibility,
extension:this.file.name.split('.').pop()
}).then((response)=>{
this.uid = response.json().data.uid;
});
},
update() {
this.saveStatus = 'Saving changes.';
return this.$http.put('/videos/' + this.uid, {
title: this.title,
description: this.description,
visibility: this.visibility
}).then((response) => {
this.saveStatus = 'Changes saved.';
setTimeout(() => {
this.saveStatus = null
}, 3000)
}, () => {
this.saveStatus = 'Failed to save changes.';
});
}
}
}
</script>
In first i save video to db along with some default value for title,description etc with ajax request,Please see Video.vue code for this
I am getting uid(unique id for video)in console from store method but when i update by clicking the save chages button i got error like this:
when i used i default uid in controller in
public function store(Request $request)
{
$uid = '158cfff622e1b7';
//....some code here
//finally return $uid
return response()->json([
'data' => [
'uid' => $uid
]
]);
}
and in Upload.vuein this line if i change uid to default 158cfff622e1b7,it works fine ie:result updated
return this.$http.put('/videos/' +'158cfff622e1b7', {
//code
});
it means i am not getting `uid` ,or something is wrong,please help me
Here is screenshot of error: http://imgur.com/a/7XGER
Error: PUT http://localhost:8000/videos/null 404 (Not Found)
I can see you are using route model binding.
Route::put('/videos/{video}','VideoController#update');
Route model binding works out of the box with ID field. If you use a different key, you need to tell your model to use that key for route model binding.
In Video model add
public function getRouteKeyName() {
return 'uid';
}
Update
In providers/RouteServiceProvider, add this inside boot()
Route::bind('video', function ($value) {
return App\Models\Video::where('uid', $value)->first();
});
If it still does not work, simply get the video and update it, the good old way
public function update(VideoUpdateRequest $request, $uid)
{
$video = Video::where('uid', $uid)->first();
$video->title = $request->title;
$video->description = $request->description;
...
$video->update();
if ($request->ajax()) {
return response()->json(null, 200);
}
return redirect()->back();
}
Replace this this.uid = response.json().data.uid; by this.uid = response.body.data.uid;
it must work,if not let me hear
Read Docs for more
I learn with laravel about last week, and now im stuck with upload file.
I have search and try another way but still not working.
I have make coding like this
public function store(Request $request)
{
$article = new Article();
$article->title = Input::get('title');
$article->description = Input::get('description');
$article->author = Input::get('author');
if($request->hasFile('image') == "")
{
$article->image = $request->image;
} else
{
$file = Input::file('image');
//upload path
$destinationPath = 'img/gallery/';
//getting timestamp
$timestamp = str_replace([' ', ':'], '-', Carbon::now()->toDateTimeString());
//setting name
$filename = $file->getClientOriginalName(). '-' .$timestamp;
$article->image = $filename;
//move to path
$file->move($destinationPath, $filename);
}
$article->save();
// sending back with message
return redirect()->route('articles.index')->with('message', 'File Success added!');
}
For Model Code
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
protected $fillable =
[
'title',
'author',
'description',
'image'
];
}
And this for view code
<div class="form-group">
{!! Form::label('image', 'Choose an image') !!}
{!! Form::file('image', null, ['class' => 'form-control', 'required' => '']) !!}
<span id="image-error" class="help-block"></span>
</div>
<div class="form-group">
{!! Form::label("image","Preview Image") !!}
<div class="image articles auth">
#if(isset($articles))
<img class="fit-cover" src="{{asset('img/gallery/'.$article->image.'')}}" id="showPicture" />
#else
<img class="fit-cover" src="http://placehold.it/625x1200" id="showPicture" />
#endif
</div>
</div>
That code success for others input. But not for file image.
In database image column is success display. But in local file image not store in folder. So the image can not display.
http://localhost:8000/img/gallery/fashion-man-person-hand.jpg
Thank you master :)
I upload image for error
enter image description here
On Ajax call from Angular controller, i am passing a complex object as data. On MVC controller object has all null values.
I have MVC view as given below, which will be the boiler plate for Register customer View.
<div data-ng-app="customer" id="customer" data-ng-controller="rootViewModel">
<h2>{{ pageHeading }}</h2>
<hr />
<form id="formElement">
<div ng-view></div>
</form>
Using AngularJS, I will be loading the register customer view, mark of register customer view given below. I have register customer function tied to button using ng-click directive.
<fieldset class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-3">Company Name</label>
<div class="col-sm-4">
<input class="form-control inputfieldValidation" ng-model="customer.Name" type="text" placeholder="Full company name" required autofocus />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">PAN</label>
<div class="col-sm-4">
<input class="form-control" ng-model="customer.Pan" type="text">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">TIN</label>
<div class="col-sm-4">
<input class="form-control inputfieldValidation" ng-model="customer.Tin" type="text" required />
</div>
</div>
<button class="btn btn-primary proceedNext" id="registerCompany" ng-click="registerCompany(customer)">Register Customer</button>
</fieldset>
I have angular controller, which has function called registerCustomer() that will be called on click of register customer. I have an ajax call inside that function as given below.
customerModule.controller("CustomerRegistration", function ($scope) {
var initialize = function () {
}
$scope.registerCompany = function (customer) {
$.ajax({
url: 'Home/RegisterCompany',//make sure url exist
data: JSON.stringify({company: customer}),//pass data to action
type:'POST',
success: function (data) {
alert(JSON.stringify(data));
//window.location.href = '#Url.Action("Order")'; //redirect
}
});
}
initialize();
});
On MVC, i have a model called Company as given below.
public class Company
{
public string Name;
public string Pan;
public string Tin;
}
and my MVC controller look as
[HttpPost]
public JsonResult RegisterCompany(Company company)
{
//Do something
return null;
}
Always I have null object on MVC controller, please help me if am missing anything. Thanks in advance
EDIT: It looks like you need a view model in mvc or a modification to your post:
public class CompanyViewModel {
public Company company { get; set; }
}
Or use data: JSON.stringify(customer) instead of data: JSON.stringify({ company: customer })
Here is a working example from a website we are developing. It uses Riot.js instead of angular, but the concepts will be similar.
See also http://www.abeautifulsite.net/postjson-for-jquery/
$.getJSON(self.baseUrl + "/SaveApplicant", $('form.#applicant').serialize(), function (response) {
if (response.errorMessage) {
RiotControl.trigger('error_message', response.errorMessage);
return;
} else {
self.packageQuote.applicant = response;
}
RiotControl.trigger("continue","applicant");
});
Or using post, per the link above
$.post(self.baseUrl + "/SaveApplicant", $('form.#applicant').serialize(), function (response) {
if (response.errorMessage) {
RiotControl.trigger('error_message', response.errorMessage);
return;
} else {
self.packageQuote.census = response;
}
RiotControl.trigger("continue","applicant");
},'json');
There is a bit more involved on the MVC side of things, to send back a json response with lower case property name prefixes:
public ActionResult SaveApplicant(Applicant model)
{
if (ModelState.IsValid)
{
var applicant = DbContext.Applicants.FirstOrDefault(row => row.Id == model.Id);
if (applicant == null) {
DbContext.Applicants.Add(model);
} else {
applicant.Clone(model); // implement as needed or use entity state modified.
}
DbContext.SaveChanges();
return FormattedJsonResult(applicant);
}
return ModelErrors();
}
public ActionResult FormattedJsonResult(object model)
{
var camelCaseFormatter = new JsonSerializerSettings();
camelCaseFormatter.ContractResolver = new CamelCasePropertyNamesContractResolver();
var result = JsonConvert.SerializeObject(model, camelCaseFormatter);
return Content(result, "application/json");
}
public ActionResult ModelErrors()
{
return FormattedJsonResult(
new
{
errorMessage =
String.Join("\n",
ModelState.Values.SelectMany(value => value.Errors).Select(error => error.ErrorMessage))
});
return View();
}