Is it possible to have Livewire events in a Datatables render function - laravel-livewire

I'm trying to open a modal and populate a form field with a model value.
The button to open the modal is embedded in the datatable config js and I'm thinking Livewire is running before the table is built.
The datatable uses ajax to populate and columnDefs to configure rows.
The JS for the config of the datatable is in a #push('scripts') in the component blade file.
The (simplified) render function for the row is:
var datatable = thetable.DataTable({
.....
render: function (data, type, full, meta){
return ('Edit');
},
.....
})
Clicking the button opens the modal but no XHR is made to the components edit function.
If I create an anchor in the same blade file as "normal" html:
<a href="#" wire:click="edit({{ 25 }})">test</button>
The XHR is called as expected.
So, I'm assuming Livewire doesn't know about the button - perhaps it ran before the table was built. Is there a way to force Livewire to wait?
I have tried to emit a Livewire event instead of wire:click = also no XHR.
I have seen the couple Laravel packages for Datatables. They don't suit.

I got this done with emitted events and component listeners.
jQuery's on to bind to the future elements clicks which livewire.emit the events.
protected listeners[] in the component respond to the emitted events.

Related

How to properly set state to allow React Bootstrap Modal to work on mapped data?

Trying to build a D.R.Y. list of vocabulary terms with React Bootstrap (v.2.2.3) using Bootstrap 5.1.
I bring in my data:
import vocData from '../data/vocData'
My component:
const VocList = () => {
const [show, setShow] = useState(false)
const handleClose = () => setShow(false)
return (
<ul className="list-inline">
{Object.keys(vocData).map((item, key) => (
<React.Fragment key={key}>
<li className="list-inline-item voc-item">
<Button>
<small>{vocData[item].title}</small>
</Button>
</li>
<Modal
show={show}
onHide={handleClose}
backdrop="static"
keyboard={false}
aria-labelledby={`contained-modal-title-${vocData[item].href}`}
centered
>
<Modal.Header closeButton>
<Modal.Title id={`contained-modal-title-${vocData[item].href}`}>
{vocData[item].title}
</Modal.Title>
</Modal.Header>
<Modal.Body>{vocData[item].content}</Modal.Body>
</Modal>
</React.Fragment>
))}
</ul>
)
}
I can see my list of vocabulary terms is working but my modal is not appearing when I click the button. I've tried to research and read through:
React-Bootstrap Multiple Modal
React-bootstrap Modal component opens/closes all modals when I map through a list
How do I get my react app to display object information in my bootstrap modal when they click on a list item?
How to use React-Bootstrap modals inside a map array method to display AJAX data on button click in React?
how to show react bootstrap modal inside the function
but I'm unable to find an answer.
How can I dynamically setState and be able to render my modal for that vocabulary term in my list?
Try to use Modal only once and not render it many times. You can show only one Modal at time anyway. I have created a subcomponent for clarity.
There are many ways how to play with state. Here the initial state is null and hides the modal. When we click on button we set state with one vocData entry. This also toggles the visibility of Modal.
Finally, when we close its again, we set our state to null. In this way we use one state for two purposes - control vision and rendering of Modal and holding data for it.

Ember re render component

I have a component with a jquery menu that transforms the DOM. I need to re render the component for initiate the structure again. The jquery menu doesn't work dinamically, so I need to re render the component.
//Parent Component hbs
<div id="container">
{{menu-jquery model=model}}
</div>
//Parent Component js
export default Ember.Component.extend({
refreshMenuData(){
callToServer()// ajax call
updateModel()// generate model from ajax response
-> //how to delete and create menu component? or re render menu component?
}
}
Thanks
A component has a function called rerenderthat you can call to force a rerender of the component. Although, I might recommend a better approach. Upon resolution of the promise that fetches your server data, manually destroy the jquery plugin and then reinit said plugin.
I found a workaround putting the component inside a conditional block. I set loading in false before the server call and true after data parsing.
{{#if loading}}
// show loading message
{{else}}
{{menu-jquery model=model}}
{{/if}}
This force the menu component to re render.
Your question is not quite clear. I am assuming that, you will be using jquery ajax for server calls inside the component. In Ember.Component, you have to use .on("didInsertElement") which works similarly as that of jQuery(document).ready(). So your component will look something like this
export default Ember.Component.extend({
_onReady: function() {
refreshMenuData();
//whatever jquery code you want to execute here
}.on('didInsertElement')
})
If you can provide your example in Ember Twiddle or JSBin, I can help you better.

force re-render of custom textfield view

How to force to re-render a custom textfield view?
I create a:
App.Select2View = Ember.TextField.extend({didInsertElement:function() {//plugin called here}});
It's included in a template form and when the form is open and I select another/different item, this custom textfield view (based on select 2) doesn't re-render but stays the same.
I have nested routes/resources. Company under companies. When I select a company I have readonly info and edit button that if clicked calls action on the Company controller to "isEditing" state, in this state a form is open. If I change the state to false it goes back into read only model (viewing the company info).
It's fine if I set it back to read only mode first, and then open another item and the select2 is rendered with this companies data.
But if it's in the isEditing state, with form open and I navigate to another company item all form input fields change according to model (such as name will change because it's binded to the name key value of the company model), but the select2 stays the same as previous.
I'm not sure how to re-render this in Ember.
This is defined as partial in template under the main company template view:
<script type="text/x-handlebars" id="company/_edit">
<p>{{input type="text" value=name}}</p>
<p>
{{view "select2"
prompt="Search for companies"
resource="results"
displayKey="text"
onSelect="addCompany"
onDeSelect="removeCompany"
}}
</p>
</script>
Any pointers are appreciated.
I'm new to Ember and my answer might not be apt, but based on my experiments the problem is that Ember caches as much as possible. So it won't re-render the view completely with the select2, only when view is in a certain state previous state followed by next state will it automatically re-render.
The solution atleast for now seems to be to add a "valueChange" method with observer on "value" change on the select2 custom TextField and make the same call as in "didInsertElement" (which executes when the view is rendered):
valueChange: function() {
Ember.run.scheduleOnce('afterRender', this, 'setupSelect2');
}.observes('value'),
Now even if I'm in the "edit" state, it will update this select2 as well, not just the standard form inputs tied specifically to the model. I can now navigate to any item in "edit" state which has form open for each item selected and values change correspondingly in the select2.

Ember Component keyboard events

In my webapp I have a search field at the top (kinda like Facebook) which is an input field and a bootstrap dropdown for result suggestions. I would like to decouple it from the controller of its container into an Ember Component. But I don't understand how to pick up events from the input field. Right now the view picks up submit (there is no submit button) and keyUp/keyDownfor navigating the dropdown. How do I listen to these events on a Component?
You can use Component the same way as you would View.
App.SearchFieldComponent = Ember.Component.extend({
value: "",
keyUp: function (e) {
console.log(e);
alert("You pressed key code " + e.keyCode);
}
});
Full jsbin.

binding controller object to a component in ember

I am trying to build a modal box component in ember. The modal box has two standard buttons, "close" and "save". I wanted to pass controller action to this component so that when save button is clicked, it calls the controller action that was passed. I call my component as :
{{#affi-modal-box title="Test title" modalId="createNewAnalyticsRunModal" controllerBinding=controller}}some message{{/affi-modal-box}}
and my component :
AS.AffiModalBoxComponent = Ember.Component.extend({
attributeBindings: ['modelId','test'],
//this is the function that gets called when save button is clicked
onSaveButtonClick : function(){
console.log(this.controllerFor('analysisTemplates'));//fails
console.log(this.get('controller'));//returns modal box component which I don't need
}
});
Any ideas how I can pass the controller object to the component??
Thanks.
The way Ember.Component's work is to be agnostic to other parts of your application, therefore rather then passing in a controller on which you want an action to be called on when something happens in your component, you do it more like in this way:
{{#affi-modal-box
title="Test title"
modalId="createNewAnalyticsRunModal"
action="actionNameOnTheController"}}some message{{/affi-modal-box}}
As you can see you set the action attribute to the action name on your controller, and then inside your component you simply call this.sendAction('action'); which will trigger whatever action name you defined earlier:
AS.AffiModalBoxComponent = Ember.Component.extend({
attributeBindings: ['modelId','test'],
//this is the function that gets called when save button is clicked
onSaveButtonClick : function(){
this.sendAction('action');
}
});
So now, whenever onSaveButtonClick is invoked it will send the action actionNameOnTheController to whatever controller is listening to it. And best of all, without knowing nothing about the controller. This is the kind of functionality that makes Ember.Component's reusable in any way.
Please see here a simple demo of the concept explained.
Hope it helps.