{"action":"opened","issue":{"url":"https://api.github.com/repos/wbraganca/yii2-dynamicform/issues/99","labels_url":"https://api.github.com/repos/wbraganca/yii2-dynamicform/issues/99/labels{/name}","comments_url":"https://api.github.com/repos/wbraganca/yii2-dynamicform/issues/99/comments","events_url":"https://api.github.com/repos/wbraganca/yii2-dynamicform/issues/99/events","html_url":"https://github.com/wbraganca/yii2-dynamicform/issues/99","id":110610186,"number":99,"title":"Separate the models and the template and profit from it","user":{"login":"lorinczelod","id":5416545,"avatar_url":"https://avatars.githubusercontent.com/u/5416545?v=3","gravatar_id":"","url":"https://api.github.com/users/lorinczelod","html_url":"https://github.com/lorinczelod","followers_url":"https://api.github.com/users/lorinczelod/followers","following_url":"https://api.github.com/users/lorinczelod/following{/other_user}","gists_url":"https://api.github.com/users/lorinczelod/gists{/gist_id}","starred_url":"https://api.github.com/users/lorinczelod/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lorinczelod/subscriptions","organizations_url":"https://api.github.com/users/lorinczelod/orgs","repos_url":"https://api.github.com/users/lorinczelod/repos","events_url":"https://api.github.com/users/lorinczelod/events{/privacy}","received_events_url":"https://api.github.com/users/lorinczelod/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-10-09T08:13:26Z","updated_at":"2015-10-09T08:13:26Z","closed_at":null,"body":"Please consider this example. It is long :(, but slightly self-explanatory :)\r\n2 files:\r\nthis widget:\r\n```\r\n<?php\r\nnamespace app\\components;\r\n\r\nuse ArrayAccess;\r\nuse Countable;\r\nuse Iterator;\r\nuse Serializable;\r\nuse yii\\base\\Exception;\r\nuse yii\\base\\Widget;\r\n\r\nclass HelloWidget extends Widget implements Iterator, ArrayAccess, Serializable, Countable\r\n{\r\n    public $array;\r\n    public $className;\r\n    private $current = null;\r\n    private $template;\r\n    private $before;\r\n    private $after;\r\n    private $models;\r\n\r\n    public function init()\r\n    {\r\n        parent::init();\r\n        ob_start();\r\n    }\r\n\r\n    public function run()\r\n    {\r\n        $this->after = ob_get_clean();\r\n        $items = [\r\n            'before:' . $this->before,\r\n            'after: ' . $this->after,\r\n            'models: ' . $this->models,\r\n            'template: ' . $this->template\r\n        ];\r\n        $return = '';\r\n        foreach ($items as $item) {\r\n            $return .= str_repeat('&nbsp', count(self::$stack) * 4) . $item . nl2br(PHP_EOL);\r\n        }\r\n        return $return;\r\n    }\r\n\r\n    /**\r\n     * Return the current element\r\n     * @link http://php.net/manual/en/iterator.current.php\r\n     * @return mixed Can return any type.\r\n     * @since 5.0.0\r\n     * @throw Exception\r\n     */\r\n    public function current()\r\n    {\r\n        if ($this->current === -1) {\r\n            return new $this->className;\r\n        }\r\n        return $this->array[$this->current];\r\n    }\r\n\r\n    /**\r\n     * Move forward to next element\r\n     * @link http://php.net/manual/en/iterator.next.php\r\n     * @return void Any returned value is ignored.\r\n     * @since 5.0.0\r\n     */\r\n    public function next()\r\n    {\r\n        if ($this->current === -1) {\r\n            $this->template = ob_get_clean();\r\n            ob_start();\r\n        }\r\n        $this->current++;\r\n    }\r\n\r\n    /**\r\n     * Return the key of the current element\r\n     * @link http://php.net/manual/en/iterator.key.php\r\n     * @return mixed scalar on success, or null on failure.\r\n     * @since 5.0.0\r\n     */\r\n    public function key()\r\n    {\r\n        $key = $this->current;\r\n        return $key;\r\n    }\r\n\r\n    /**\r\n     * Checks if current position is valid\r\n     * @link http://php.net/manual/en/iterator.valid.php\r\n     * @return boolean The return value will be casted to boolean and then evaluated.\r\n     * Returns true on success or false on failure.\r\n     * @since 5.0.0\r\n     */\r\n    public function valid()\r\n    {\r\n        if ($this->current === -1) {\r\n            return true;\r\n        }\r\n        if (isset($this->array[$this->current])) {\r\n            return true;\r\n        }\r\n        $this->models = ob_get_clean();\r\n        ob_start();\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Rewind the Iterator to the first element\r\n     * @link http://php.net/manual/en/iterator.rewind.php\r\n     * @return void Any returned value is ignored.\r\n     * @since 5.0.0\r\n     */\r\n    public function rewind()\r\n    {\r\n        $this->before = ob_get_clean();\r\n        ob_start();\r\n        $this->current = -1;\r\n    }\r\n\r\n    /**\r\n     * Whether a offset exists\r\n     * @link http://php.net/manual/en/arrayaccess.offsetexists.php\r\n     * @param mixed $offset <p>\r\n     * An offset to check for.\r\n     * </p>\r\n     * @return boolean true on success or false on failure.\r\n     * </p>\r\n     * <p>\r\n     * The return value will be casted to boolean if non-boolean was returned.\r\n     * @since 5.0.0\r\n     * @throws Exception not implemented\r\n     */\r\n    public function offsetExists($offset)\r\n    {\r\n        throw new Exception(__FUNCTION__ . ' is  not implemented yet!');\r\n    }\r\n\r\n    /**\r\n     * Offset to retrieve\r\n     * @link http://php.net/manual/en/arrayaccess.offsetget.php\r\n     * @param mixed $offset <p>\r\n     * The offset to retrieve.\r\n     * </p>\r\n     * @return mixed Can return all value types.\r\n     * @since 5.0.0\r\n     * @throws Exception not implemented\r\n     */\r\n    public function offsetGet($offset)\r\n    {\r\n        throw new Exception(__FUNCTION__ . ' is  not implemented yet!');\r\n    }\r\n\r\n    /**\r\n     * Offset to set\r\n     * @link http://php.net/manual/en/arrayaccess.offsetset.php\r\n     * @param mixed $offset <p>\r\n     * The offset to assign the value to.\r\n     * </p>\r\n     * @param mixed $value <p>\r\n     * The value to set.\r\n     * </p>\r\n     * @return void\r\n     * @since 5.0.0\r\n     * @throws Exception not implemented\r\n     */\r\n    public function offsetSet($offset, $value)\r\n    {\r\n        throw new Exception(__FUNCTION__ . ' is  not implemented yet!');\r\n    }\r\n\r\n    /**\r\n     * Offset to unset\r\n     * @link http://php.net/manual/en/arrayaccess.offsetunset.php\r\n     * @param mixed $offset <p>\r\n     * The offset to unset.\r\n     * </p>\r\n     * @return void\r\n     * @since 5.0.0\r\n     * @throws Exception not implemented\r\n     */\r\n    public function offsetUnset($offset)\r\n    {\r\n        throw new Exception(__FUNCTION__ . ' is  not implemented yet!');\r\n    }\r\n\r\n    /**\r\n     * String representation of object\r\n     * @link http://php.net/manual/en/serializable.serialize.php\r\n     * @return string the string representation of the object or null\r\n     * @since 5.1.0\r\n     * @throws Exception not implemented\r\n     */\r\n    public function serialize()\r\n    {\r\n        throw new Exception(__FUNCTION__ . ' is  not implemented yet!');\r\n    }\r\n\r\n    /**\r\n     * Constructs the object\r\n     * @link http://php.net/manual/en/serializable.unserialize.php\r\n     * @param string $serialized <p>\r\n     * The string representation of the object.\r\n     * </p>\r\n     * @return void\r\n     * @since 5.1.0\r\n     * @throws Exception not implemented\r\n     */\r\n    public function unserialize($serialized)\r\n    {\r\n        throw new Exception(__FUNCTION__ . ' is  not implemented yet!');\r\n    }\r\n\r\n    /**\r\n     * Count elements of an object\r\n     * @link http://php.net/manual/en/countable.count.php\r\n     * @return int The custom count as an integer.\r\n     * </p>\r\n     * <p>\r\n     * The return value is cast to an integer.\r\n     * @since 5.1.0\r\n     */\r\n    public function count()\r\n    {\r\n        return count($this->array);\r\n    }\r\n}\r\n```\r\nand a view-like :) :\r\n```\r\n<?php\r\n\r\nuse app\\components\\HelloWidget;\r\nuse yii\\base\\Model;\r\n\r\nclass MyModel extends Model\r\n{\r\n    public $var = 'default';\r\n}\r\n\r\necho '<h4>Example with no models</h4>';\r\n\r\n$myModel = [];\r\n\r\n$static = HelloWidget::begin(\r\n    [\r\n        'array' => $myModel,\r\n        'className' => MyModel::className(),\r\n    ]\r\n);\r\n\r\necho 'Before foreach' . nl2br(PHP_EOL);\r\n\r\nforeach ($static as $key => $item) {\r\n    echo $key . ' => ' . $item->var . nl2br(PHP_EOL);\r\n}\r\n\r\necho 'After foreach' . nl2br(PHP_EOL);\r\n\r\nHelloWidget::end();\r\n\r\n\r\necho '<h4>Example with models</h4>';\r\n\r\n$myModel = [\r\n    new MyModel(['var' => 'dummy']),\r\n    new MyModel(['var' => 'something']),\r\n];\r\n\r\n$static = HelloWidget::begin(\r\n    [\r\n        'array' => $myModel,\r\n        'className' => MyModel::className(),\r\n    ]\r\n);\r\n\r\necho 'Before foreach' . nl2br(PHP_EOL);\r\n\r\nforeach ($static as $key => $item) {\r\n    echo $key . ' => ' . $item->var . nl2br(PHP_EOL);\r\n}\r\necho 'After foreach' . nl2br(PHP_EOL);\r\n\r\nHelloWidget::end();\r\n\r\necho '<h4>Example with \\'nested\\' models</h4>';\r\n\r\n$myModel = [\r\n    new MyModel(['var' => 'dummy']),\r\n    new MyModel(['var' => 'something']),\r\n];\r\n\r\n$static = HelloWidget::begin(\r\n    [\r\n        'array' => $myModel,\r\n        'className' => MyModel::className(),\r\n    ]\r\n);\r\n\r\necho 'Before foreach' . nl2br(PHP_EOL);\r\n\r\nforeach ($static as $key => $item) {\r\n    echo $key . ' => ' . $item->var . nl2br(PHP_EOL);\r\n    $myModelInside = [\r\n        new MyModel(['var' => 'inside anything']),\r\n    ];\r\n    $static_inside = HelloWidget::begin(\r\n        [\r\n            'array' => $myModelInside,\r\n            'className' => MyModel::className(),\r\n        ]\r\n    );\r\n    echo 'Before foreach inside' . nl2br(PHP_EOL);\r\n    foreach ($static_inside as $key2 => $item2) {\r\n        echo $key2 . ' =>(inside) ' . $item2->var . nl2br(PHP_EOL);\r\n    }\r\n    echo 'After foreach inside' . nl2br(PHP_EOL);\r\n    HelloWidget::end();\r\n}\r\necho 'After foreach' . nl2br(PHP_EOL);\r\n\r\nHelloWidget::end();\r\n```"}}