Автозаполнение полей предыдущих значений

Я делаю небольшое приложение в Yii Framework, для которого моя база данных выглядит примерно так

 === Invoices ===
  id (PK)
  customer_id
  invoice_title
  order_no
  invoice_issue_date
  due_date
  description

  === Customers ===
  id (PK)
  email_address
  customer_name
  address
  city
  state
  postal_code
  description

Я визуализировал Customer model в Invoice model, так что я могу ввести все значения для обеих моделей в single Invoice form. Но есть одна проблема, давайте предположим, что у меня есть имя клиента xyz, которое у меня было saved before. Теперь, когда я собираюсь again fill the Customer name with xyz , он должен показывать all the fields of both models like invoice_title,order_no,invoice_issue_date,due_date,description,email_address,customer_name,address etc. in that input fields of the form, чтобы мне не приходилось re-enter all the fields again. Итак, как этого можно добиться в Yii framework. Любая помощь и предложения будут весьма ценными. При необходимости можно поделиться дополнительными разъяснениями по кодам, которые я сделал. Пожалуйста, помогите мне. Я полностью застрял здесь.


person NewUser    schedule 28.06.2012    source источник
comment
Вы можете отправить запрос AJAX, когда имя будет заполнено (или при каждом нажатии клавиши и попытке поиска с частичным именем), найти связанные данные и отправить их обратно в представление. Затем, с указанными данными, обновите форму.   -  person adamors    schedule 28.06.2012
comment
спасибо @Ors.За ответ!!!На самом деле у меня нет хорошего представления об Ajax..Можете ли вы рассказать мне об этом больше?   -  person NewUser    schedule 28.06.2012
comment
Тогда вам следует обратиться к документации/книгам; В этом случае достаточно jQuery.   -  person adamors    schedule 28.06.2012
comment
Хорошо, не будет ли у клиента много счетов? как вы планируете выбирать, какую информацию о счете заполнять в форме?   -  person bool.dev    schedule 06.07.2012
comment
да... у клиента много счетов. Я выбрал имя клиента из раскрывающегося списка, который уже был сохранен. Теперь, когда я выберу имя, оно должно получить все данные этого клиента в форме.   -  person NewUser    schedule 06.07.2012


Ответы (3)


Для этого, как уже упоминалось, вам понадобится ajax и немного javascript. Логика примерно такая:

  1. Когда в раскрывающемся списке для имени клиента выбрано значение, инициируйте вызов ajax для получения информации об этом пользователе. Это можно легко сделать с помощью опции ajax, которая доступна как дополнительная опция htmlOption для некоторых помощников элементов html в CHtml, как часть clientChange.

    echo $form->dropDownList($model,'customer_name',CHtml::listData(Customers::model()->findAll(),'id','customer_name'),
       array(// htmlOptions
         'ajax'=>array(// special htmlOption through clientChange, for ajax
               'type'=>'GET', 
               'url'=>$this->createUrl('controllername/customerdetails'),// action that will generate the data
               'data'=>'js:"id="+$(this).val()',// this is the data that we are sending to the action in the controller
               'dataType'=>'json',// type of data we expect back from the server
               'success'=>'js:updateFields'// a javascript function that will execute when the request completes successfully
         )
       )
     );
    

    Документацию по указанным выше параметрам для ajax можно увидеть в документация jquery по ajax.

  2. Затем на стороне сервера найдите конкретного клиента и отправьте ответ в браузер. Пример:

    // in the controllername code an action that will return the values as json
    public function actionCustomerdetails($id){
        $var=Customers::model()->findByPk($id);
        echo CJSON::encode($var);
    }
    
  3. Когда вы получите ответ сервера, заполните соответствующие поля. Это можно сделать в обратном вызове функции успеха для ajax, в приведенном выше коде это было updateFields:

    Yii::app()->clientScript->registerScript('update','
        function updateFields(data, textStatus, jqXHR){
            // select each input field by id, and update its value
            $("#Customers_postal_code").val(data.postal_code);
            $("#Customers_city").val(data.city);
            $("#Customers_address").val(data.address);
            // similarly update the fields for the other inputs
        }
    ');
    

Примечания: У вашего клиента может быть много счетов, поэтому вопрос будет заключаться в том, какой счет выбрать, учитывая имя клиента. Это то, с чем вам придется справиться, я думаю, что в моем ответе достаточно кода, чтобы вы начали.

Чтобы узнать идентификаторы полей ввода, вы можете просто проверить сгенерированный HTML.

person bool.dev    schedule 06.07.2012
comment
дайте мне знать, если вам нужны какие-либо разъяснения - person bool.dev; 06.07.2012
comment
можете ли вы сказать мне, что означает jqXHR в function updateFields(data, textStatus, jqXHR){}? Почему он используется здесь? - person NewUser; 11.07.2012
comment
Вы читали ссылку на документацию, которую я добавил в ответ? jqXHR — это тип объекта jquery. поиск Google легко выдаст тонны ссылок. он используется для вызовов ajax. - person bool.dev; 11.07.2012
comment
Да, я понял... кстати, этим он вставляет идентификатор в поле customer_name базы данных. - person NewUser; 12.07.2012
comment
да, вы можете догадаться, почему это происходит? - person bool.dev; 12.07.2012
comment
я думаю для этого $var=Customers::model()->findByPk($id); - person NewUser; 12.07.2012
comment
не совсем так, но это связано с этой строкой кода, подумайте немного усерднее, вы близки... - person bool.dev; 12.07.2012
comment
Я думаю, что я использовал 'data'=>'js:"id="+$(this).val()'в htmlOptions, а в этом id присвоено это значение. Это правильно? - person NewUser; 12.07.2012
comment
опять же, это связано (ближе, чем раньше), но не источник проблемы, еще один шаг назад, и вы ее получите... - person bool.dev; 12.07.2012
comment
давайте продолжим это обсуждение в чате - person NewUser; 12.07.2012

Вы можете сделать это в два этапа, чтобы:

  1. При первоначальном отображении представления у покупателя запрашивается email address или customer_name.

  2. Действие контроллера, которому отправляется форма, затем извлекает данные из модели Customer для отправленных email address или customer_name (я буду использовать email_address в своем примере ниже). После извлечения вы можете отобразить представление формы единого счета с данными, предварительно заполненными для клиента, если они доступны.

Затем эту концепцию можно было бы реализовать следующим образом:

<?php
// file: controllers/InvoiceController.php
class InvoiceController extends CController
{
  // ... other controller functions

  public function actionCreate($step = null)
  {
    $invoice  = new Invoice;
    $customer = new Customer;

    # Form has been submitted:
    if ( isset($_POST['Customer']) )
    {
      # The submitted form was Step 1:
      if ( $step == 1 )
      {
        # make sure the submitted email address is valid
        $customer->setAttributes($_POST['Customer']);
        if ( $customer->validate(array('email_address')) )
        {
          # retrieve the customer by email_address
          $customer = Customer::model()->findByAttributes(array('email_address' => $_POST['Customer']['email_address']));
        }

        $this->render('createstep2', array('invoice' => $invoice, 'customer' => $customer));
      }

      # The submitted form was Step 2:
      elseif ( $step == 2 )
      {
        $income->setAttributes($_POST['Invoice']);
        $customer->setAttributes($_POST['Customer']);

        # save the data
        if ( $customer->save() )
        {
          $invoice->customer_id = $customer->id;
          if ( $invoice->save() )
          {
            $this->redirect(array('view', 'id' => $invoice->id));
          }
        }

        # display any errors
        $this->render('createstep2', array('invoice' => $invoice, 'customer' => $customer));
      }
    } 

    $this->render('createstep1', array('invoice' => $invoice, 'customer' => $customer));
  }

  // ... other controller functions
}
?>

Вы можете разделить это на два отдельных действия контроллера, если хотите.

Для представления «Шаг 1» у вас может быть следующее:

<!-- file: views/invoice/createstep1.php -->
<h1>Create Invoice: Step 1</h1>

<div class="form">

<?php
$form = $this->beginWidget('CActiveForm', array(
  'id'=>'invoice-form',
  'enableAjaxValidation'=>false,
  'action'=>array('invoice/create','step' => 1)
)); 
?>

  <?php echo $form->errorSummary($customer); ?>

  <div class="row">
    <?php echo $form->labelEx($customer,'email_address'); ?>
    <?php echo $form->textField($customer,'email_address', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($customer,'email_address'); ?>
  </div>

  <div class="row buttons">
    <?php echo CHtml::submitButton('Next'); ?>
  </div>

<?php $this->endWidget(); ?>

</div><!-- form -->

Шаг 2, вы можете выглядеть так, как у вас уже есть. Может быть, что-то вроде:

<!-- file: views/invoice/createstep2.php -->
<h1>Create Invoice: Step 2</h1>

<div class="form">

<?php
$form = $this->beginWidget('CActiveForm', array(
  'id'=>'invoice-form',
  'enableAjaxValidation'=>false,
  'action'=>array('invoice/create','step' => 2)
)); 
?>

  <?php echo $form->errorSummary($invoce); ?>
  <?php echo $form->errorSummary($customer); ?>

  <h2>Customer Details</h2>
  <div class="row">
    <?php echo $form->labelEx($customer,'email_address'); ?>
    <?php echo $form->textField($customer,'email_address', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($customer,'email_address'); ?>
  </div>

  <!-- If the customer already exists, these field should be pre-populated: -->

  <div class="row">
    <?php echo $form->labelEx($customer,'customer_name'); ?>
    <?php echo $form->textField($customer,'customer_name', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($customer,'customer_name'); ?>
  </div>

  <div class="row">
    <?php echo $form->labelEx($customer,'address'); ?>
    <?php echo $form->textField($customer,'address', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($customer,'address'); ?>
  </div>

  <div class="row">
    <?php echo $form->labelEx($customer,'city'); ?>
    <?php echo $form->textField($customer,'city', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($customer,'city'); ?>
  </div>

  <div class="row">
    <?php echo $form->labelEx($customer,'state'); ?>
    <?php echo $form->textField($customer,'state', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($customer,'state'); ?>
  </div>

  <div class="row">
    <?php echo $form->labelEx($customer,'postal_code'); ?>
    <?php echo $form->textField($customer,'postal_code', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($customer,'postal_code'); ?>
  </div>

  <div class="row">
    <?php echo $form->labelEx($customer,'description'); ?>
    <?php echo $form->textField($customer,'description', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($customer,'description'); ?>
  </div>


  <h2>Order Details</h2>

  <div class="row">
    <?php echo $form->labelEx($invoice,'invoice_title'); ?>
    <?php echo $form->textField($invoice,'invoice_title', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($invoice,'invoice_title'); ?>
  </div>

  <div class="row">
    <?php echo $form->labelEx($invoice,'order_no'); ?>
    <?php echo $form->textField($invoice,'order_no', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($invoice,'order_no'); ?>
  </div>

  <div class="row">
    <?php echo $form->labelEx($invoice,'invoice_issue_date'); ?>
    <?php $form->widget('zii.widgets.jui.CJuiDatePicker', array(
        'model'     => $invoice,
        'attribute' => 'invoice_issue_date',
        'value'     => $invoice->invoice_issue_date,
        'options'   => array(
          'showButtonPanel' => false,
          'changeYear'      => true,
          'dateFormat'      => 'yy-mm-dd',
        ),
      )); ?>
    <?php echo $form->error($invoice,'invoice_issue_date'); ?>
  </div>

  <div class="row">
    <?php echo $form->labelEx($invoice,'due_date'); ?>
    <?php $form->widget('zii.widgets.jui.CJuiDatePicker', array(
        'model'     => $invoice,
        'attribute' => 'due_date',
        'value'     => $invoice->due_date,
        'options'   => array(
          'showButtonPanel' => false,
          'changeYear'      => true,
          'dateFormat'      => 'yy-mm-dd',
        ),
      )); ?>
    <?php echo $form->error($invoice,'due_date'); ?>
  </div>

  <div class="row">
    <?php echo $form->labelEx($invoice,'description'); ?>
    <?php echo $form->textField($invoice,'description', array('size'=>60,'maxlength'=>255)); ?>
    <?php echo $form->error($invoice,'description'); ?>
  </div>


  <div class="row buttons">
    <?php echo CHtml::submitButton('Create'); ?>
  </div>

<?php $this->endWidget(); ?>

</div><!-- form -->
person Turgs    schedule 01.07.2012
comment
@newuser Это ответ на ваш вопрос или у вас есть отзывы? - person Turgs; 03.07.2012
comment
Спасибо @Turgs за ваш ответ. Извините, я не посещал этот форум пару дней, поэтому не ответил на ваш ответ. да.. Я видел ваш код. Я не реализовал это. Но из этого кода я думаю, что я должен click on save, но I don't want to click on the button. Я просто хочу, чтобы когда one value is entered in a single input, это было fetch all the values in the formfields of the corresponding model без нажатия на save button. Так что для этого я думаю, что нужен ajax. Итак, как этого можно добиться? - person NewUser; 03.07.2012

Вы проверили виджет Yii Autocomplete? И вам не придется беспокоиться о реализации AJAX. Он делает это за вас.

Yii Framework: автозаполнение CJui

Более индивидуальное решение для автозаполнения по этой ссылке.

Yii Framework: custom-autocomplete-display-and-value -представление

person Arjun Abhynav    schedule 30.06.2012
comment
Спасибо @Arjun за ваш ответ. Я видел две ссылки, которые вы разместили в своем ответе. Я думаю, что второй пост можно использовать в этом. Но ajax не найден, поэтому я должен нажать на форму отправки. Но мое требование - получить все значения определенного поля из связанных моделей, не нажимая кнопку отправки. Итак, как это сделать? - person NewUser; 03.07.2012