alpine component fails to execute on livewire update - javascript

I have an alpine.js component with livewire data save. https://github.com/TerrePorter/CustomCountrySelectBox.git
I am trying to load two and eventually three of these in sequence on the page. First, the country then when that is selected, I update the state/region, and finally when that is updated I update the city.
The problem is when I update the state/region the alpine.js code does not execute when livewire refreshed that part of the page.
I also tried to make it work all on one page, a select box that updates the next select box, but it would always fail to load the second array.
Here is the relevant part of the template
<div class="p-6">
<lable>Please select your location: </lable>
#if ($country == '')
#component('components.country-select-box', ['countryJson' => $countryJson])#endcomponent
#endif
#if ($stateJson != '')
#component('components.state-select-box', ['stateJson' => $stateJson])#endcomponent
#endif
</div>
Here is part of the livewire code where I update the state's JSON file.
public function updatedCountry() {
$this->stateJson = $this->getStateJson();
}
public function getStateJson() {
$r = Countries::where('short_name', '=', $this->country)->with('states')->first();
$ret = [];
foreach ($r->states as $index => $item) {
$ret[] = ['title' => $item->state_name, 'value' => $item->id];
}
return json_encode($ret);
}
And finally as mentioned before this is the select box dropdown I am using, https://github.com/TerrePorter/CustomCountrySelectBox.git

Related

Saving Values to Backend from TextBoxes using React Flux Pattern

I have several text boxes and a save button
Each text box value is loaded using the following approach
{
this.getElement('test3lowerrangethreshold', 'iaSampling.iaGlobalConfiguration.test3lowerrangethreshold',
enums.IASamplingGlobalParameters.ModerationTest3LowerThreshold)
}
private getElement(elementid: string, label: string, globalparameter: enums.IASamplingGlobalParameters): JSX.Element {
let globalParameterElement =
<div className='row setting-field-row' id={elementid}><
span className='label'>{localeHelper.translate(label)}</span>
<div className="input-wrapper small">
<input className='input-field' placeholder='text' value={this.globalparameterhelper.getDataCellContent(globalparameter, this.state.globalParameterData)} />
</div>
</div>;
return globalParameterElement;
}
Helper Class
class IAGlobalParametesrHelper {
public getDataCellContent = (globalparameter: enums.IASamplingGlobalParameters, configdata: Immutable.List<ConfigurationConstant>) => {
return configdata?.find(x => x.key === globalparameter)?.value;
}
}
This works fine. Now the user is allowed to update these text values.And on click of save the changes should be reflected by calling a web api .
I have added an onlick event like this
<a href='#' className='button primary default-size' onClick={this.saveGlobalParameterData}>Save</a>
Now inorder to save the data i need a way to identify the text element which has changed.For that i have added an update method within the Helper class
public updateCellValue = (globalparameter: enums.IASamplingGlobalParameters, configdata: Immutable.List<ConfigurationConstant>,updatedvalue:string) => {
let itemIndex = configdata.findIndex(x => x.key === globalparameter);
configdata[itemIndex] = updatedvalue;
return configdata;
}
and return the updated configdata ,and i plan to call this method in the onchange event of every text box like this
<input className='input-field' placeholder='text' onchange={this.setState({ globalParameterData: this.globalparameterhelper.updateCellValue(globalparameter, this.state.globalParameterData, (document.getElementById(elementid) as HTMLInputElement).value})}
But this does not seem like a correct approach as there are number of syntactical errors. I initially got the data using an actioncreator like this.Please advice.
samplingModerationActionCreator.getGlobalParameters();
samplingModerationStore.instance.addListener(samplingModerationStore.SamplingModerationStore
.IA_GLOBAL_PARAMETER_DATA_GET_EVENT,
this.getGlobalParameterData);
}

DropDownItem doesn't load items after update(Javascript) partial view

I have the following functionality: A user registers a series of data in a form, after sending the form and saving it in the database, it is redirected to a second form, where it must load the rest of the information, it is possible that in this second form, contains a lot of values of the first form, but this is not always the case, that is why in this second form there is a button that allows "copy" the data of the first form, to reduce data entry.
As I did?
I created a main view, where the form is loaded as a partial view with the empty model fields, so that the user can enter the information if it is not the same as the first form
Main View:
<div id="partialView">
#Html.Partial("_CreatePartialResponsable", Model)
</div>
In the form that contains the partial view, there is a dropdowlist that is filled through a web service. This dropdow is filled correctly when loading the blank form, the first time.
DropDownList in the partial view
<div class="form-group col-md-6">
#Html.LabelFor(model => model.SeguroNombre, htmlAttributes: new { #class = "titulocampo" })
<select id="SeguroNombre" name="SeguroNombre" class="form-control"><option value=""></option></select>
#Html.ValidationMessageFor(model => model.SeguroNombre, "", new { #class = "text-danger" })
</div>
With this script, the dropdowlist is loaded, I call it from the main view in the document.ready event (it's works perfectly)
function llenaDropDownSeguros(url, valor) {
var data = { nombre: valor };
$.post(url, data).done(function (data) {
if (data.isError) {
muestraError(data.Titulo, data.Mensaje);
} else {
for (var i = 0; i < data.length; i++) {
$('#SeguroNombre').append('<option value=' + data[i].codigoSeguro + '>' + data[i].descripcion + '</option > ');
}
}
});
};
If the user wants to "copy" the information of the previous form, press a button that executes the following function js to go to the server, search the data and return the same partial view, but with the corresponding fields loaded. Re render?
Script to "copy" data
function loadPartial(url, valor) {
$("#esperar").show();
var data = { cedula: valor };
$.post(url, data).done(function (data) {
if (!data.isError) {
$("#esperar").hide();
$("#partialView").html(data);
} else {
$("#esperar").hide();
muestraError(data.Titulo, data.Mensaje);
}
}).fail(manejarErrorAjax);
};
What is the problem?
After the copy button is pressed and the partial view is reloaded with the "copied" data, the dropdownlist items are no longer there. I understand that they are lost, because of course, when doing a partial view reloaded, that dropdown comes empty, that I understood. What I do not understand is because, after reloading that partial view, there is no way I can fill the dropdowlist again. By test I made a change and in the click event of the ddl, I called the loadPartial function to see if it worked, but even though in the browser console, it is seen that the function is executed and the data object takes 94 values, these they are not loaded to the dll.
Can you help me with this problem?

Laravel + Ajax - How to query items by query string from GET

So I have a products page with different products. There I have some checkboxes for color and size. On checkbox change I want to make an ajax call to my Laravel controller with the needed colors and sizes to query the products and return them back as json and just change the old products with my new ones using javascript. When copying/pasting the full url in another tab, I want to get the products page with the queried products. How can I do that? Here is my code:
<ul class="color-list">
#foreach($availableColors as $color)
<li><input type="checkbox" name="color" value="{{ $color->name }}"></li>
#endforeach
#foreach($availableSizes as $size)
<li><input type="checkbox" name="size" value="{{ $size }}">{{ $size }}</li>
#endforeach
Here is my route:
Route::get('/products/{gender}/{subcategory_name}', [
'uses' => 'ProductsController#showProducts',
'as' => 'products']);
Here is my controller:
public function showProducts($gender, $subcategory_name)
{
$subcategory = Subcategory::where('name', $subcategory_name)->first();
$gender = Gender::where('gender', $gender)->first();
$availableSubcategories = $this->getAvailableSubcategories($subcategory->category->id);
$availableColors = $this->getAvailableColors($gender, $subcategory);
$availableSizes = $this->getAvailableSizes($gender, $subcategory);
$priceRange = $this->getPriceRange($gender, $subcategory);
return view('products', [
'gender' => $gender,
'subcategory' => $subcategory,
'availableSubcategories' => $availableSubcategories,
'availableColors' => $availableColors,
'availableSizes' => $availableSizes,
'priceRange' => $priceRange
]);
}
Code, advice, solutions would be appriciated. Thanks in advance :)
Hmm, I'd maybe look at using Session or Cache. I wouldn't manipulate the url (it's ugly and can be modified by user).
So in your controller method (note the Request injection):
public function showProducts(Request $request, $gender, $subcategory_name)
{
// if a session already exists, clear it
if ($request->session()->has('some_name'))
$request->session()->forget('some_name');
// your current logic
...
// store new session ($products = save products array to variable)
$request->session()->put('some_name', $products);
}
Then in your view check if session exists:
if (Session::has('some_name')) {
#foreach(Session('some_name') as $some_name)
...
#endforeach
}
else {
...
}
You could even do a ternary on your loops, etc:
#foreach(((Session::has('some_name')) ? Session('some_name')['available_sizes'] : $availableSizes) as $size)
<li><input type="checkbox" name="size" value="{{ $size }}">{{ $size }</li>
#endforeach
None of this was tested. I just wrote it out by hand. But it should give you an idea to work with!
You need to manipulate the browser history of the browser by calling history.pushState to modify the url without reloading the whole page every ajax call request.
Check this link https://developer.mozilla.org/en-US/docs/Web/API/History_API or you can use this javascript plugin https://github.com/browserstate/history.js/

Yii2: Change Gridviews' DataProvider on button click

I have 3 seperate dataProviders for my Gridview, one with Saved data, one with Unsaved data and one with both.
Now this is what I'm trying to accomplish:
If you click on saved, the dataProvider changes to the one with saved data.
I'm trying it like this:
<?php
if($i == 1){
$dataProvider = $dataProviderSaved;
} elseif($i == 2) {
$dataProvider = $dataProviderNotsaved;
} else {
$dataProvider = $dataProviderBoth;
};
\yii\widgets\Pjax::begin(['id' => 'gridview', 'timeout' => false,
'enablePushState' => false, 'clientOptions' => ['method' => 'POST']]) ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
//regular gridview..
\yii\widgets\Pjax::end(); ?>
Javascript:
var i = $i;
$("#saved").click(function(){
i=1;
$.pjax.defaults.timeout = false;//IMPORTANT
$.pjax.reload({container:"#gridview"});
});
', \yii\web\View::POS_READY);
So, I've just read that changing PHP variables inside JS is 'impossible'.
How would I accomplish this?
Is there a better way?
Do I need 3
DataProviders? (This means 3 find()'s inside of the controller)
If I understood properly you don't need 3 dataProviders. You should use GridView's FilterSelector option to treat that external element as part of GridView's filter.
For example
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'filterSelector' => "input[name='ModelSearch[_selection]'],",
...
Then, in your Filter Model you filter depending on that value
switch($this->_selection) {
case 'Saved':
$query->andFilterWhere([...]);
break;
case 'Unsaved':
$query->andFilterWhere([...]);
break;
case 'Both':
$query->andFilterWhere([...]);
break;
Don't forget to add the _selection attribute to your Model class and to rules() as 'safe' in the Search Model class.
You can try in two ways:
The first the simpler you assign to each button (saved, unsaved, both) the call of three separate cation of your controller
that invoke each a respective view connected to a single gridview each of these latter with the appropriate dataprovider
The second consists of controller you have the three dataprovider different as this example
return $this->render('viewYourView', [
'/modelContribuente' =>$modelContribuente,
'dataProviderOne' => $providerOne,
'dataProviderTwo' => $providerTwo,
'dataProviderThree' => $providerThree,
]);(
In a single View you can create your three gridview everyone who uses the dataprovider appropriate and then visalizzare or hide gridviewn with JQuery functions controlled by buttons

give two function in one button in Yii framework

I have a question about Yii framework, i have problem with submit button, i want to given two fungsi save and update in one submit button, can anyone tell me how to set that function on form ?
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
i change 'Save' with 'Update' it's still have error Primary key added, how i can create two function update and save in one push button ?
public function actionCreate()
{
$model=new TblUasUts;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['TblUasUts']))
{
$model->attributes=$_POST['TblUasUts'];
if($model->save())
$this->redirect(array('view','id'=>$model->nim_mhs));
}
if(isset($_POST['TblUasUts'])
{
$model->attributes=$_POST['TblUasUts'];
if($model->update())
$this->redirect(array('view','id'=>$model->nim_mhs));
}
$this->render('update',array(
'model'=>$model,
));
}
In your form, you can use something like :
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Update'); ?>
</div>
As far as processing different actions on the backend code, there are a few options, for example, you could :-
Direct your form to different URLs
Set a (hidden) field (for example ID) and parse for that.
Use the default action from the activeForm, which directs back to the invoking action, for example actionCreate(), or actionUpdate()
In light of your updates, please extend your controller as per my initial suggestion to have another action actionUpdate()
The main difference between the actionCreate(), or actionUpdate() actions is that the Create action create a new (empty) TblUasUts object, while the Update action populates the TblUasUts object from the database.
public function actionCreate()
{
$model=new TblUasUts;
...
... Do things with $model ...
...
$model->save();
}
public function actionUpdate
{
// The id of the existing entry is passed in the url. for example
// ...http:// .... /update/id/10
//
$model = TblUasUts::model()->findByPK($_GET['id']);
...
... Do things with $model ...
...
$model->save();
}

Categories