Looking at docs https://laravel-livewire.com/docs/2.x/events#from-js
working with Livewire component inside of javascript
<script>
Livewire.emit('postAdded')
</script>
I do not see what Livewire is ? Declared var ? How can I get it.
I need from JS code get value of some var and run component method.
How can I do it?
Modified Block # 2:
Defining in template of my component :
<div class="admin_page_container" id="facilities_admin_page_container">
...
In method of my alpinejs component I do
function adminFacilitiesComponent() {
return {
getSubmitLabel: function (component) {
const doc = document.getElementById("facilities_admin_page_container");
console.log('doc::')
console.log(doc)
var updateMode = window.livewire.find(doc.getAttribute("wire:updateMode"))
// But I got error : index.js:31 Uncaught (in promise) TypeError: Cannot read property '$wire' of undefined
// I see content of doc in browser's console : https://prnt.sc/1sdu4f1
console.log('updateMode::')
console.log(updateMode)
In my component I have defined :
namespace App\Http\Livewire\Admin;
...
class Facilities extends Component
{
...
public $updateMode = 'browse';
I just try to get value of $updateMode in JS getSubmitLabel function...
Thanks!
To answer your question where the livewire global object is comming from: you injected livewire scripts in the body of your layout:
<html>
<head>
...
#livewireStyles
</head>
<body>
...
#livewireScripts
</body>
</html>
https://laravel-livewire.com/docs/2.x/installation
The livewire global object is available via window.Livewire. The method you are looking for is probably
Livewire.emitTo(componentName, eventName, ...params)
Make sure that the livewire object is actually available when you are calling this method.
For all available methods see https://laravel-livewire.com/docs/2.x/reference
To get a component in javascript try:
const doc = document.getElementById("myComponent");
window.livewire.find(doc.getAttribute("wire:id"))
Livewire recommends that you use AlpineJS for most of your JavaScript needs, but it does support using tags directly inside your component's view.
<!DOCTYPE html>
<html>
<head>
#livewireStyles
</head>
<body>
<p>This is My Component Call </p>
#livewire('blog-component')
#livewireScripts
<script>
Livewire.emit('postAdded') //also write Javascript Hear
document.addEventListener('livewire:load', function () {
// Your JS here.
})
</script>
Reference
https://laravel-livewire.com/docs/2.x/inline-scripts
https://laravel-livewire.com/docs/2.x/reference
Related
The rest of the blade files are reading values from the controller well. The ..layout/app.blade file is getting undefined variable $names from ..Layout/App.php.
Below is my App.php. I have tried to dd($names) seems its the App.php is not being reached.
<?php
namespace App\Http\Livewire\Layouts;
use Livewire\Component;
class App extends Component
{
public $names ="Alex Boey";
public function mount(){
dd($this->names);
}
public function render()
{
return view('livewire.layouts.app');
}
}
app.blade.php
<head>
#livewireStyles
</head>
<body>
<div>{{$names}}</div>
{{ $slot }}
#livewireScripts
</body>
View Image to see the files on IDE
A Livewire component can only have a single root element. You're using Livewire to load in the full app view. That simply won't work.
lostika already provided the answer you're looking for;
Replace the <div>{{$names}}</div> in your app.blade with <livewire:layouts.app/>, and then inside the view of your Livewire component:
<div>
{{$names}}
</div>
If the app.blade that you posted is the same as your Livewire component's view, then you need to move that to a separate, non-Livewire location.
I have a unit testing set up using Mocha and Chia run in a Chrome browser as shown below. To enforce the Component class' static htmlTagName property, I am using an error in the Component base-class that gets thrown if the htmlTagName property is not overwritten by a child class. The problem that I am encountering is that the error thrown in the constructor does not appear to be caught by chia.assert.throw(...) instead it causes the test to fail as shown in the link below. The behavior I expected to see is that chia catches the expected error and the test passes. I have included the relevant code below.
Unit-test error result image
<!DOCTYPE html>
<!-- index.html -->
<html>
<head>
<title>Mocha Tests</title>
<link rel="stylesheet" href="../../node_modules/mocha/mocha.css">
</head>
<body>
<div id="mocha"></div>
<script src="../../node_modules/mocha/mocha.js"></script>
<script src="../../node_modules/chai/chai.js"></script>
<script type="module" class="mocha-init">mocha.setup('bdd')</script>
<!-- load code you want to test here -->
<!-- load your test files here -->
<script type='module' src="./objective-styles.test.js"></script>
<script type='module' src="./base-classes.test.js"></script>
<script type='module' src="./calendar-widget.test.js"></script>
<script type="module">
mocha.run();
</script>
</body>
</html>
//base-classes.ts
export class Component extends HTMLElement {
static htmlTagName: string | undefined;
constructor() {
super();
// Enforce classes having htmlTagName
if(!this.htmlTagName) {
throw (`${this.constructor.name} htmlTagName property is undefined`);
}
}
get htmlTagName() {
return this.constructor.htmlTagName;
}
set htmlTagName(htmlTagName: string) {
this.constructor.htmlTagName = htmlTagName;
}
}
// base-classes.test.ts
import { GuiTestingUtils } from "./gui-testing-utils.js";
import { Component, Widget} from "../../app/js/widgets/base-classes.js";
describe("Component test suite", ()=>{
let sandbox: HTMLDivElement;
let fakeDOM: ShadowRoot;
let style: HTMLStyleElement;
before(()=>{
// set up the sandbox
let body = document.querySelector('body');
sandbox = GuiTestingUtils.addSandbox(body!);
fakeDOM = sandbox.shadowRoot!;
style = document.createElement('style');
});
beforeEach(()=>{
// clean the sandbox
GuiTestingUtils.refreshSandbox(sandbox);
fakeDOM.appendChild(style);
});
after(()=>{
// tear down the sandbox
let body = document.querySelector('body');
body!.removeChild(sandbox);
});
it("Component does throw error if htmlTagName is not defined", ()=>{
// chia.assert.throw does not catch the error as expected...
customElements.define("base-component", Component);
chai.assert.throw(()=>{
document.createElement("base-component");
});
});
});
I'm developing a module for OpenCart 3.x and I'm trying to insert some JavaScript code into website's front via $this->load->view() method but cannot get it to work, as the JS code doesn't appear in the DOM.
Here's an excerpt of my code:
/catalog/controller/extension/module/mymodule.php
class ControllerExtensionModuleMyModule extends Controller {
public function index() {
$this->load->language('extension/module/mymodule');
$this->load->model('checkout/order');
$this->load->model('setting/setting');
$this->load->model('design/layout');
$this->load->model('catalog/category');
$this->load->model('catalog/manufacturer');
$this->load->model('catalog/product');
$this->load->model('catalog/information');
$data['js_output'] = "Some JS output";
return $this->load->view('extension/module/mymodule', $data);
}
}
catalog/view/theme/default/template/extension/module/mymodule.twig
<script type="text/javascript">
console.log('This is working!");
</script>
Am I missing something?
Add an external javascript file via controller like this:
$this->document->addScript('catalog/view/javascript/my-external-script.js');
But if it's a block of javascript code, you don't need to edit controller file, just add it to your view file (twig or tpl):
<script type="text/javascript">
console.log("This is working!");
</script>
Finally you may need to clear caches (vqmod, ocmod, twig etc ...).
EDIT
If you want to prepare your javascript code in the controller, follow this:
controller
$data['js_output'] =
'<script type="text/javascript">
console.log("This is working!");
</script>';
Twig
{{ js_output }}
I have finally fixed the issue. It was a problem with the install() method not correctly inserting and loading the design/layout ($this->model_design_layout->getLayouts()).
If your module needs to insert a layout into the layout_module table, make sure you have the correct layout_id, code(which must be your module name), position (i.e: 'content_bottom') and sort_order(which often times is > 90).
I have built a html page with some internal templates. See url jsfiddle:
http://jsfiddle.net/hoven002/jQTDH/
What is the best method to make the templates external and how?
Regards,
Kenneth
The best method, in my opinion, is to use this plugin: https://github.com/ifandelse/Knockout.js-External-Template-Engine.
It enables a new template engine that will pull templates from external files. It has some configuration options as well to determine where the templates are pulled from.
I've written a function that loads templates, without any dependency but jQuery. You must mark each <script> tags you want to be dynamically loaded with the attribute data-template-src and put there the path of your HTML file. Following is the code and an example.
Warning: since it uses AJAX to load templates, it needs an HTTP server (it won't work locally with file:// protocol)
/main.js
// Loads all the templates defined with the tag data-template-src.
// Returns a promise that fulfills when all the loads are done.
function loadTemplates() {
var templateLoads = [];
$('[data-template-src]').each(function () {
var templateElement = $(this);
var templateUrl = templateElement.attr('data-template-src');
// Load the template into the element and push the promise to do that into the templateLoads array
templateLoads.push(
$.get(templateUrl)
.done(function (data) {
templateElement.html(data);
})
);
});
return $.when.apply($, templateLoads);
}
// When all templates are loaded, apply bindings
loadTemplates().done(function () {
ko.applyBindings({}, document.getElementById("htmlDoc"));
});
/index.html
<html id="htmlDoc">
<body>
<div data-bind="template: { name: 'exampleTemplate' }"></div>
<script type="text/html" id="exampleTemplate" data-template-src="/assets/exampleTemplate.html"></script>
<script src="/jquery.js"></script>
<script src="/knockout.js"></script>
<script src="/main.js"></script>
</body>
</html>
/assets/exampleTemplate.html
<h1>Hello world</h1>
<div data-bind="template: { name: 'exampleSubTemplate' }"></div>
/assets/exampleSubTemplate.html
<h2>How do you do?</h2>
I got the Facebook login/logout functionality to work, but had to do it with this un-elegant code like this:
<script type="javascript">
function loadfb() {
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol + '//connect.facebook.net/es_LA/all.js';
document.getElementById('fb-root').appendChild(e);
};
</script>
<body onload="loadfb()">
I plan on putting that Facebook login button on all the pages of the site, so I really don't want to have this function called onload of every page.
Is this function necessary? I don't completely understand what it is for. What is a better way to do this so I can take it out of my onload?
Thanks!
This code is for asynchronous loading of the Facebook JavaScript SDK. What it does is create the tag
<script async scr="https://connect.facebook.net/es_LA/all.js" ></script>
inside the <div id="fb-root"></div> element. While loading the SDK asynchronously is considered better practice, you can leave out this code and manually enter the script tag yourself - eg:
<div id="fb-root"></div>
<script src="http://connect.facebook.net/es_LA/all.js"></script>
<script>
FB.init({
...
});
</script>