I'd like to load Vue Component via AJAX dynamically and render its template.
Main Vue Instance:
const router = new VueRouter({
path: '/vue/actions/',
mode: 'history'
});
var app = new Vue({
el: '#mainContainer',
router,
data: {
mainContent: ''
},
methods: {
action: function (url) {
alert(url);
this.$router.push({ path: '/vue/actions/?'+url});
console.log(this.$route.query);
},
actions: function () {
var action;
if (!this.$route.query.action || this.$route.query.action == 'main') {
action = 'index';
} else {
action = this.$route.query.action;
}
var mainContent;
fetch('/vue/actions/?content_type=json&action='+action).then((response) => {
if(response.ok) {
return response.json();
}
throw new Error('Network response was not ok');
}).then((json) => {
this.$router.push({ path: '/vue/actions/', query: { action: json.action }});
// this.mainContent = json.template;
console.log(json.template);
this.dynamicComponent = json.template;
}).catch((error) => {
console.log(error);
});
}
},
created: function () {
this.actions();
}
})
Initial Page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="" />
<meta name="author" content="" />
<meta http-equiv='cache-control' content='no-cache'>
<meta http-equiv='expires' content='0'>
<meta http-equiv='pragma' content='no-cache'>
<script type="text/javascript" src="/js/vue.min.js"></script>
<script src="/js/vue-router.js"></script>
</head>
<body>
<template><div><component :is="dynamicComponent"></component></div></template>
<div id="mainContainer" v-html="mainContent"></div>
<script type="text/javascript" src="/js/main.js"></script>
</body>
</html>
Component I'd like to load via AJAX:
Vue.component('dynamicComponent', {
template: '<div>Dynamic Component!</div>'
});
Is it possible to load such Vue Componet and render its template (with an ability to use Vue data bindings in the Component template)?
Here is how I got what I need:
Main Vue Instance:
const router = new VueRouter({
path: '/vue/actions/',
mode: 'history'
});
var app = new Vue({
el: '#mainContainer',
router,
data: {
mainContent: ''
},
methods: {
action: function (url) {
this.$router.push({ path: '/vue/actions/?'+url});
console.log(this.$route.query);
},
actions: function () {
var action;
if (!this.$route.query.action || this.$route.query.action == 'main') {
action = 'index';
} else {
action = this.$route.query.action;
}
Vue.component('dynamic-component', (resolve) => {
import('/vue/actions/?content_type=javascript&action='+action).then((component) => {
resolve(component.default);
});
});
}
},
created: function () {
this.actions();
}
})
Main/Initial Page Body:
<body>
<div id="mainContainer">
<dynamic-component></dynamic-component>
</div>
<script type="text/javascript" src="{{.__web_root_folder}}/js/main.js"></script>
</body>
Component code that I'm loading when needed:
export default {
template: '<div>Async Component! {{.test}}</div>',
data () {
return {
test: 'Works!'
}
}
}
Thanks to #MazinoSUkah !
Related
I'm getting a particular error and can't understand where the problem is.
No more explanations, code will illustrate it better than me :
Here are my routes :
Route::get('/', 'HomeController#index')->name('home');
Route::delete('home/{home}', 'HomeController#destroy')->name('home.destroy');
Here is my homeController :
class HomeController extends Controller
{
public function index()
{
return view('view');
}
public function destroy()
{
ddd('Hello World');
}
}
Here is my view 'view.blade.php' :
#extends('layouts.layout')
#section('content')
<component></component>
#endsection
Here is my layout :
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="base-url" content="{{ url('/') }}">
<title>{{ config('app.name', 'Laravel') }}</title>
#yield('styles')
</head>
<body>
<div id="app">
#yield('content')
</div>
<!-- Scripts -->
<script src="{{ mix('js/app.js') }}"></script>
#yield('scripts')
</body>
</html>
Here is my bootstrap.js :
window._ = require('lodash');
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token)
{
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
}
else
{
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
Here is my app.js :
require('./bootstrap');
window.Vue = require('vue');
Vue.prototype.baseUrl = document.head.querySelector('meta[name="base-url"]').content;
Vue.component('component', require('./components/ComponentComponent.vue').default);
const app = new Vue({
el: '#app',
});
And here is my component :
<template>
<button v-on:click="delete()">BUTTON</button>
</template>
<script>
export default {
methods: {
delete()
{
if ( confirm('Confirm ?') )
{
axios.delete(`${this.baseUrl}/home/6`)
.then( (response) =>
{
console.log('Succeeded');
})
.catch( (error) =>
{
console.log('Failed');
});
}
}
},
created()
{
this.$nextTick( () =>
{
});
}
}
</script>
What I actually have is a console.log message : "Succeeded" but as a response I get a page full of Ignition elements giving the error :
Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
The GET method is not supported for this route. Supported methods:
DELETE.
When I change delete into get in my route : I get the error
DELETE http://test.test/home/6 404 (Not Found)
Like I'm really sending a DELETE Request but at a given time, it changes in a GET request Type... Inexplicable...
No need to say that I need serious help here, thank you for helping !
Have you tried using a resource controller?
https://laravel.com/docs/5.7/controllers#resource-controllers
Also you should follow the rules of the REST API.
So a get request would be: http://test.test/home?id=6
A delete request would be: http://test.test/home/6
So in axios you want to use parameters when you send the get request to
axios.get('/home', {
params: {
id: 6
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.finally(function () {
// always executed
});
But a delete request would go to
'http://test.test/home/' + id
https://github.com/axios/axios
I believe that because when you change the
DELETE request http://test.test/home/6 to a GET request
Laravel is looking for PUT, PATCH, DELETE
this is why you are getting this error:
Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
The GET method is not supported for this route. Supported methods: PUT, PATCH, DELETE.
In your index method here:
public function index()
{
$id = $request->input('id');
# DO SOMETHING WITH THIS ID HERE
return view('view')->with(['data' => 'WHATEVER YOU DID ABOVE']);
}
Is where you would handle this id parameter to fetch the id of 6.
https://laravel.com/docs/5.7/requests#retrieving-input
OR
You could add this to your controller:
public function show($id)
{
}
and than route to it:
Route::get('/{id}', 'HomeController#show')->name('home');
https://laravel.com/docs/4.2/routing#route-parameters
// Have you tried this way of doing the Axios delete?
axios({
method: 'delete',
url: '/home/6'
}).then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.finally(function () {
// always executed
});
I'm starting to work with vuejs and I'm trying to make a http get call without sucess. I've tried several example showing how to do that but I get the following error in my console: this.$http is undefined.
html
<!doctype html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.21/css/uikit.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.21/js/uikit.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.21/js/uikit-icons.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.19.1/vis.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.19.1/vis.min.css" rel="stylesheet" type="text/css"/>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<p v-bind:title='message'>
{{ message }}
<p>
<button v-on:click='changeView("matrice")'>get data</button>
</div>
</body>
<script type="text/javascript" src="/front/lala_web/matrice.js"></script>
</html>
js
var app = new Vue({
el: '#app',
data: {
message: 'Empty data'
},
methods:{
changeView: function(v){
this.$http.get('/view/'+v)
.then(function(resp){
this.message = resp.data;
})
.catch(function(){alert('Error')});
}
}
})
I'been able to get a http get call working using the following js, but doing so doesn't change data.message value of vuejs and I get the following error data is not defined.
js
var app = new Vue({
el: '#app',
data: {
message: 'Empty data'
},
methods:{
changeView: function(v){
var viewUrl = '/view/'
$.ajax({
url: viewUrl+v,
method: 'GET',
success: function (resp) {
if (resp.error == false){
console.log(resp)
data.message = resp.data
}
},
error: function (error) {
console.log(error)
}
});
}
}
})
You need to reference this.message not data.message. Also, you'll need to save a reference to this outside the scope of the ajax call, since this in the success handler doesn't refer to the Vue instance:
changeView: function(v){
var viewUrl = '/view/'
var self = this;
$.ajax({
url: viewUrl+v,
method: 'GET',
success: function (resp) {
if (resp.error == false){
console.log(resp)
self.message = resp.data
}
},
error: function (error) {
console.log(error)
}
});
}
I would like to attach an event to the button at the end of the sap.m.Select control to call the backend for values displayed in the dropdown of that control. How can this be achieved?
Thanks!
Please check this running example. Hope it gives you some hints. Thank you!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script id="sap-ui-bootstrap" type="text/javascript" src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js" data-sap-ui-libs="sap.m" data-sap-ui-theme="sap_belize" data-sap-ui-xx-bindingSyntax="complex">
</script>
<script id="myXmlView" type="ui5/xmlview">
<mvc:View height="100%" xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" controllerName="MyController" displayBlock="true">
<Select id="test_select" forceSelection="false" items="{
path: '/ProductCollection',
sorter: { path: 'ProductId' }
}">
<core:Item key="{ProductId}" text="{ProductId}" />
</Select>
</mvc:View>
</script>
<script>
sap.ui.getCore().attachInit(function() {
"use strict";
sap.ui.define([
"jquery.sap.global",
"sap/ui/core/mvc/Controller",
"sap/ui/model/json/JSONModel",
], function(jQuery, Controller, JSONModel) {
"use strict";
return Controller.extend("MyController", {
onInit: function() {
this.oModel = new JSONModel();
this.getView().setModel(this.oModel);
var that = this;
var oSelect = this.getView().byId("test_select");
oSelect.ontap = function(oEvent) {
if (!oSelect.isOpen()) {
oSelect.setBusy(true);
that.oModel.setData({});
var callBackend = function() {
that.simulateBackendData();
oSelect.setBusy(false);
}
setTimeout(callBackend, 3000);
}
sap.m.Select.prototype.ontap.apply(this, arguments);
};
},
simulateBackendData: function() {
var oData = {
"ProductCollection": [{
"ProductId": Math.random()
},
{
"ProductId": Math.random()
},
{
"ProductId": Math.random()
},
{
"ProductId": Math.random()
},
]
};
this.oModel.setData(oData);
}
});
});
sap.ui.xmlview({
viewContent: jQuery("#myXmlView").html()
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody" id="content" role="application">
</body>
</html>
Although the story id properly prefilled, renderToString() still renders the app without the state being filled in via mapStateToProps().
I use selectors to get data from state.
The problem is, that the props are not being populated. On the client, everything works.
Anyone ideas?
THANKS!
Here's the code for the server side operation:
app.use('*', (req, res) => {
// // Create a new Redux store instance
const sagaMiddleware = createSagaMiddleware();
let middleware = applyMiddleware(sagaMiddleware);
// middleware = compose(middleware,thunkMiddleware)
const initialState = {};
const store = createStore(reducers,initialState,middleware);
store.runSaga = sagaMiddleware.run;
store.close = () => store.dispatch(END);
const routes = getRoutes(store.getState)
const tres = res;
const url = req.originalUrl;
const urlSplit = url.split('/');
match({ routes: routes, location: req.url }, (err, redirect, props) => {
if (err) {
tres.status(500).send(err.message)
} else if (redirect) {
tres.redirect(redirect.pathname + redirect.search)
} else if (props) {
if(urlSplit[1]==='story'){
let slug = urlSplit[2];
store.runSaga(waitAll([[getStoryBySlug,host,slug], [getAbout, host]])).done.then(() => {
res.end(renderPage(store,props,tres));
});
}else{
store.runSaga(waitAll([[getAbout, host], [getHome, host]])).done.then(() => {
res.end(renderPage(store,props,tres));
});
}
} else {
tres.status(404).send('Not Found')
}
})
});
And here are the actual renderPage and renderFullPage functions:
const renderPage = (store,props,res) => {
// Render the component to a string
const html = renderToString(
<Provider store={store}>
<RouterContext {...props}/>
</Provider>
)
let head = Helmet.rewind();
const preloadedState = fromJS(store.getState());
return renderFullPage(html, preloadedState, head);
}
const renderFullPage = (html, preloadedState, head) => {
return `
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
${head.title.toString()}
${head.meta.toString()}
${head.link.toString()}
<script src="https://use.typekit.net/yzi3zgu.js"></script>
<script>try{Typekit.load({ async: true });}catch(e){}</script>
<link href="/assets/fonts/GillSans/stylesheet.css" rel="stylesheet"/>
<link href="/assets/vendors/fullpage/jquery.fullPage.css" />
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous" />
<link rel="shortcut icon" href="/assets/icons/favicon-inv.png" />
<link rel="stylesheet" href="/styles.css" />
</head>
<body>
<div id="root">${html}</div>
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState)}
</script>
<script src="/vendor.js"></script>
<script src="/main.js"></script>
</body>
</html>
};
I need get changes in my array then i edit data in user controls. In this snipet my example. As I did not try, I can not do it. How I can make it?
Please try with the below code snippet.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.common.min.css">
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.default.min.css">
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.dataviz.min.css">
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.dataviz.default.min.css">
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.mobile.all.min.css">
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.3.1119/js/kendo.all.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.3.1119/js/angular.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.3.1119/js/jszip.min.js"></script>
</head>
<body>
<a id="btnShowTest" href="#">Test</a>
<div id="layout"></div>
<script>
var root = {};
root.data =
[
{
code: 1,
name: "Test1",
status: true
},
{
code: 2,
name: "Test2",
status: true
},
{
code: 3,
name: "Test3",
status: false
},
];
$(function () {
$("#btnShowTest").kendoButton().click(function (e) {
Show();
});
root.ds = new kendo.data.DataSource(
{
pageSize: 10,
schema:
{
model:
{
id: "code",
fields:
{
code:
{
editable: false,
nullable: true
},
name:
{
type: "string"
},
status:
{
type: "boolean"
},
}
}
},
data: root.data
});
$("#layout").kendoListView(
{
dataSource: root.ds,
template: kendo.template($("#managersTemplate").html())
});
});
function Show() {
//root.ds.sync();
// var arr = root.ds.data();
var arr = root.data;
var str = "";
for (var i = 0; i < arr.length; ++i) {
str += arr[i].status + ", ";
}
alert(str);
}
function testclick(obj) {
var arr = root.data;
for (var i = 0; i < arr.length; ++i) {
if (arr[i].code == $(obj).attr('id')) {
arr[i].status = $(obj).prop('checked');
}
}
}
</script>
<script type="text/x-kendo-tmpl" id="managersTemplate">
<div >
<input type="checkbox" data-bind="checked:status" name="status" id="#:code#" onclick="testclick(this)" />
<span class="checkbox">#:name#</span>
</div>
</script>
</body>
</html>
Let me know if any concern.