Yii 2.0: Load data from internal/external source to fill form fields

5 followers

Overview

This wiki is to show you how to use jQuery get and JSON to get data from a dropdown/any form field and fill form fields with the values instantaneously. First, I'll give example use cases of what I'm going to teach you so you can quickly see if this is for you.

Use Case

Lets say you have a database table that stores locations. These locations have an address associated with them (id, name, address, city, state, zip).

You may also have another table that stores user locations (id, user_id, address, city, state, zip).

You allow the user to select a location from a dropdown. This dropdown will now get the data for that location and input the information into the current form and fill the address, city, state, and zip from it.

Introduction

The above is just a very simple example. You can use what I'm about to show you for numerous things including pulling data from an external API and filling your form data with it. One way I personally use this is on my address forms I have the user type in a postal code and then I pull the city, state, and country from it.

Data we are pulling from

For this example we will have a model called "locations" this locations model will have a database table with the following fields.

  • id

  • name

  • address

  • city

  • state

  • zip

Where we are putting the Data

i will also have another model called UserLocations with the following fields

  • id

  • user_id

  • address

  • city

  • state

  • zip

This model will also have a controller called UserLocations.

first we will go in our controller and create a function to retrieve the location and return it's data via JSON.

Controller

UserlocationsContrller

use yii\helpers\Html;
use yii\web\Response;
 
public function actionGetLocationAddress($id) {        
        Yii::$app->response->format = Response::FORMAT_JSON;
        echo Locations::find()->where('id = :id', [':id' => $id])->one();
    }

Since the function is camelCased you should note that it needs to accessed like. userlocations/get-location-address

if it wasn't camelCased i.e.

actionGetlocationaddress

it would be accessed like

userlocations/getloctionaddress

Form

Now we go to our UserLocationForm here for simplicity of this example I am not putting any styling, id's, placeholders etc. I am also placing the JS inline. It should be noted that it is recommend to register your JS using Yii2 asset functions.

<?php
 
use frontend\models\Locations;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
?>
<?php  $form = ActiveForm::begin();?>
<?= $form->field($model, 'location')->dropDownList(ArrayHelper::map(Locations::find()->all(), 'id', 'name')) ?>
<?= $form->field($model, 'city')->textInput(); ?>
<?= $form->field($model, 'city')->textInput(); ?>
<?= $form->field($model, 'state')->textInput(); ?>
//this is type tel so it propmts the number pad on mobile devices.
<?= $form->field($model, 'zip')->input('tel'); ?>
<?php ActiveForm::end(); ?>
 
<script type="text/javascript">
    //the dropdown list id; This doesn't have to be a dropdown it can be any field type.
    $("#user-locations-location").on("change", function() {
        //the dropdown list selected locations id
        var id = $(this).val();
        //call the action we created above in the conrller
        $.get("<?= Url::to(['userlocations/get-location-address']); ?>", {id: id}, function(data) {
            //get the JSON data from the action
            var data = $.parseJSON(data);
            //check if the system found any data            
            if (data !== null) {
                //if yes fill the form field with the ids address,city, state & zip.
                //we use .blur because yii will fire validation for those field after they are filled
                $("#user-locations-address").val(data.address).blur();
                $("#user-locations-city").val(data.city).blur();
                $("#user-locations-state").val(data.state).blur();
                $("#user-locations-zip").val(data.zip).blur();
            } else {
                //if data wasn't found the alert.
                alert('We\'re sorry but we couldn\'t load the the location data!');
            }
        });
    });
</script>

Also, to get the proper ids (#user-location-address) you must use a tool like firebug or Firefox inspect element to get them. By default yii will do (all lowercase) #modelname-attributename / #modelname-attribute_name;

i.e.

locations model state field will become

locations-state

or locations model postal_code will become

locations-postal_code

You can also set the Id in the options array of the form field.

<?= $form->field($model, 'state')->textInput(['id'=>'state']); ?>

However, if you manually set them then make sure you set the options array selectors in the form to match or client side validation won't work.

<?= $form->field($model, 'state',['selectors' => ['input' => '#state']])->textInput(['id'=>'state']); ?>

That is all you have to do for this very basic example. You can also switch the url portion of the jQuery to an external JSON API to get data. If you have questions post below and I'll try and answer them if I can.

Total 4 comments

#19998 report it
eldorado2768 at 2016/12/12 04:56pm
How I got it to work Yii2

1) Changed url format in javascript function

From this:

$.get("<?= Url::to(['userlocations/get-location-address']); ?>", {id: id},

To this:

$.get("userlocations/get-location-address", {id: id},

2) Changed Controller function that queries data

From this:

echo Locations::find()->where('id = :id', [':id' => $id])->one();

To this:

return Locations::find()->where('id = :id', [':id' => $id])->one();

Now it works for me.

#19309 report it
zelenin at 2015/05/18 04:26am
RE: Example without ugly hacks

@skworden oh, you must read about pdo binding because you're not right

#19308 report it
skworden at 2015/05/17 10:44pm
RE: Example without ugly hacks

Edit: corrected wiki @zelenin good catch.

#19304 report it
zelenin at 2015/05/17 03:36am
Example without ugly hacks


public function actionGetLocationAddress($id)
{
    Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    echo Locations::find()->where('id = :id', [':id' => $id])->one();
}
 

Leave a comment

Please to leave your comment.

Write new article