Undefined variable $names - laravel-livewire

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.

Related

How to use Livewire component inside of javascript?

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

Can't get to add JS to front via $this->load->view

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).

Is it possible to add class for main route DOMelement?

As in title, is it possible to add something like
classNames
in Component but inside Route or Controller object?
Edited
In application template I add few elements
<header></header>
<div class="content"></div>
<footer></footer>
And as result on page I have:
<div id="ember1122" class="ember-view">
<header></header>
<div class="content"></div>
<footer></footer>
</div>
And I'd like to have
<div id="ember1122" class="ember-view customClassName">
At present, you can't do what you want in a straight forward way.
1. But you can wrap application.hbs content with root div.
Define rootElement in index.html
<div id="my-app" class="customClassName">
{{content-for "body"}}
</div>
inside app.js file, you can change rootElement
import Ember from 'ember';
export default Ember.Application.extend({
rootElement: '#my-app'
});
2.May be you can even try applying styles to application.hbs div using css like
#my-app > .ember-view { // customClassName style goes here }
I don't think this is possible. Altough documentation states that "controller is a specialized component", in fact they are not at all similar.
Component is a subclass of Ember.View. Every time a Component is rendered, there's created a new instance that is hooked to specific part of DOM, has hooks related to rendering, and is aware of DOM elements that it contains.
Controller is an abstract singleton, subclass of Ember.Object. It has functions, properties and actions hooked to rendered template, but doesn't know itself anything about DOM it's attached to.

{{link-to}} within a model's attribute?

Given something like a post model with a body attribute, is there a way to get ember to dynamically render {{link-to}}'s within the body attribute?
Example:
// The model
post = {
body: `
{{#link-to "posts.index"}}
<h1>The "{{#link-to}}" is rendered literally!</h1>
{{/link-to}}`
}
// The .hbs file
<div class="container">
{{postBody post.body}}
</div>
// Helper function to avoid escaping the HTML
export function postBody(postBody) {
return Ember.String.htmlSafe(postBody);
}
export default Ember.Helper.helper(postBody);
The only thing I can think to do is enter a static link, which would cause a full page reload.
I think what you are looking for is the compile function. See here for more information. You would call it like this:
Ember.Handlebars.compile(this.get('post.body');

Getting the content rendered inside a #each ember template helper, without the #each content binding

/START description of why
I'm doing a 'load more' type of interaction: user gets at bottom of a page, I load more content.
As I'm using a plugin that formats content in a 'pinterest-style' (masonry), I need to take the output of a rest call, formatted using an ember view, and i'm doing something like:
<div id="list">
</div>
<div id="hidden" style="display:none">
{{#each item in App.itemsController}}
test {{item.id}}
<br />
{{/each}}
</div>
What I want to do is, load the content in the hidden div, and then pass its HTML generated content to the plugin to process in my formatted list view.
If I just copy the #hidden content, the Ember scripts get in, and on subsequent 'load more', content is inserted in the #list, in addition of going in the #hidden div.
That's because I copied the entire handlebars.
So I get rid of the container tag, the one I supposed was wrapping the controller content binding, but even when stripping it from the content I pass to #list, the #list still auto-updates when a 'load more' is called.
I know that's a dirty hackish thing, but in order to improve performance in the client I must take a similar route.
/END description of why
//ACTUAL QUESTION ;)
Given this background, the question is, stripping the container metamorph script tags (like the ones here below), and just take the content inside them, shouldn't get rid of the auto-updating content functionality?
<script id="metamorph-X-start" type="text/x-placeholder"></script>
//ALL THE CONTENT
<script id="metamorph-X-end" type="text/x-placeholder"></script>
Inside those, I just have the actual content generated, like:
<script id="metamorph-9-start" type="text/x-placeholder"></script>
test <script id="metamorph-59-start" type="text/x-placeholder"></script>2873<script id="metamorph-59-end" type="text/x-placeholder"></script>
<br>
<script id="metamorph-9-end" type="text/x-placeholder"></script>
<script id="metamorph-10-start" type="text/x-placeholder"></script>
test <script id="metamorph-60-start" type="text/x-placeholder"></script>2872<script id="metamorph-60-end" type="text/x-placeholder"></script>
<br>
<script id="metamorph-10-end" type="text/x-placeholder"></script>
The alternative is programmatically render the template inside a variable and process that, which is surely a better way of doing this, but I just wonder how the #each binding works internally as I thought the metamorph was doing that.
Have you looked into using a CollectionView and calling the plugin through the didInsertElement callback?
e.g.
MyList = Ember.CollectionView.extend({
itemViewClass: 'App.ListItem',
didInsertElement: function(){
view.$().jqueryPlugin({ ... })
}
})