====
open
====

.. js:function:: open(options, callback, async)

**domain**: client 

**language**: javascript

**class** :doc:`Item class </refs/client/item_api>`

Description
===========

Call ``open`` to sends a request to the server for obtaining an item dataset. 

The ``open`` method can have the following parameters:

* ``options`` - an object that specifies the parameters of the request sent to 
  the server
* ``callback``: if the parameter is not present, the request is sent to the 
  server synchronously, otherwise, the request is executed asynchronously and 
  after the dataset is received, the callback is executed
* ``async``: if its value is true, and callback parameter is missing, the request 
  is executed asynchronously 
  
The order of parameters doesn't matter.

The method initializes the item 
:doc:`fields <at_fields>`,
formulates parameters of a request, based on the ``options`` and triggers the 
:doc:`on_before_open <on_before_open>` event 
handler if one is defined for the item.

After that it sends the request to the server. If ``callback`` 
parameter-function is specified, the request is executed asynchronously, 
otherwise - synchronouslly. 

The server, after recieving the request, checks if the corresponding item on the 
server (item of the 
:doc:`task tree </programming/task_tree>` 
with the same ID attribute) has the
:doc:`on_open </refs/server/item/on_open>`
event handler. If so it executes this event handler and returns the result of 
the execution to the client, otherwise generates a SELECT SQL query, based on 
parameters of the request, executes this query using the
:doc:`execute_select </refs/server/task/m_execute_select>`
method of the task and returns the result to the client.

The client, after receiving the result of the request, sets 
:doc:`active <at_active>`
to true, the
:doc:`item_state <at_item_state>` 
to browse mode, goes to the first record of the dataset, triggers 
:doc:`on_after_open <on_after_open>` 
and 
:doc:`on_filters_applied <on_filters_applied>`
event handlers (if they are defined for the item), and updates controls.

Then it calls ``callback`` function if it was specified.

Options
-------

The ``options`` object parameter can have the following attributes:

* ``expanded`` - if the value of this attribute is true, the SELECT query, generated
  on the server, will have JOIN clauses to get lookup values of the 
  :doc:`lookup fields </programming/data/lookup_fields>`
  , otherwise no lookup values will be returned. The default value if ``true``.
  
* ``fields`` - use this parameter to specify the WHERE clause of the SELECT 
  query. This parameter is a list of field names. If it is omitted, the fields 
  defined by the
  :doc:`set_fields <m_set_fields>`
  method will be used. If the
  :doc:`set_fields <m_set_fields>`
  method was not called before the ``open`` method execution, all the fields 
  created by a developer will be used.

* ``where`` - use this parameter to specify how records will be filtered in the 
  SQL query. This parameter is an object of key-value pairs, where keys are
  field names, that are followed, after double underscore, by a filtering symbols
  (see
  :doc:`Filtering records </programming/data/filtering_records>`
  ). If this parameter is omitted, values
  defined by the
  :doc:`set_where <m_set_where>`
  method will be used. If the
  :doc:`set_where <m_set_where>`
  method was not called before the ``open`` method execution, and ``where`` 
  parameter is omitted, then the values of 
  :doc:`filters </programming/data/filters>` 
  defined for the item will be used to filter records.
  
* ``order_by`` - use ``order_by`` to specify sort order of the records. This 
  parameter is a list of field names. If there is a sign '-' before the field 
  name, then on this field records will be sorted in decreasing order. If this 
  parameter is omitted, a list defined by the   
  :doc:`set_order_by <m_set_order_by>`
  method will be used.

* ``offset`` -  use ``offset`` to specify the offset of the first row to return.

* ``limit`` - use ``limit`` to limit the output of a SQL query to the first 
  so-many rows.

* ``funcs`` - this parameter can be a an object of key-value pairs, where key is 
  a field name and value is function name that will be applied to the field in
  the SELECT Query

* ``group_by`` - use ``group_by`` to specify fields to group the result of the 
  query by. This parameter must be a list of field names.

* ``open_empty`` - if this parameter is set to ``true``, the application does 
  not send a request to the server but just initializes an empty dataset. 
  The default value  if ``false``.

* ``params`` - use the parameter to pass some user defined options to be used in
  the 
  :doc:`on_open </refs/server/item/on_open>`
  event handler on the server. This parameter must be an object of key-value pairs

.. note::
    When the 
    :doc:`paginate <at_paginate>`
    attribute of the item is set to ``true`` and a table is created by the
    :doc:`create_table <m_create_table>`
    method, the ``limit`` and ``offset``  parameters are set internally by the
    table depending on its row number and current page.

Examples
========

.. code-block:: js

    function get_customer_sales(task, customer_id) {
        var date1 = new Date(new Date().setYear(new Date().getFullYear() - 5)),
            date2 = new Date(),
            invoices = task.invoices.copy();
    
        invoices.open({
            fields: ['customer', 'invoicedate', 'total'], 
            where: {customer: customer_id, invoicedate__ge: date1, invoicedate__le: date2},
            order_by: ['invoicedate']
        });
    }

.. code-block:: js

    function get_customer_sales(task, customer_id) {
        var date1 = new Date(new Date().setYear(new Date().getFullYear() - 5)),
            date2 = new Date(),
            invoices = task.invoices.copy();
    
        invoices.set_fields(['customer', 'invoicedate', 'total']);
        invoices.set_where({customer: customer_id, invoicedate__ge: date1, invoicedate__le: date2});
        invoices.set_order_by(['invoicedate']);
        invoices.open();
    }

.. code-block:: js

    function get_sales(task) {
        var sales = task.invoices.copy();

        sales.open({
            fields: ['customer', 'id', 'total'], 
            funcs: {'id': 'count', 'total': 'sum'}, 
            group_by: ['customer'], 
            order_by: ['customer']
        });
    }
