private function insertFormFields() {

		$this->html = preg_replace_callback(

			'/\{\s*(dropdown|input|image|button|textarea|options|checkbox|selectbox|label|element):(\w+)(?:\s+(\{.*?\}))?\s*\}/i',

			function($matches) {

				// check whether element was assigned

				if(empty($this->elements[$matches[2]])) {

					if($this->onlyAssignedElements) {
						throw new HtmlFormException(sprintf("Element '%s' not assigned to form.", $matches[2]), HtmlFormException::INVALID_MARKUP);
					}

				}

				else {

                    // validate JSON attribute string

                    if (!empty($matches[3])) {

                        $attributes = json_decode($matches[3], true, 2);

                        if (is_null($attributes)) {
                            throw new HtmlFormException(sprintf("Could not parse JSON attributes for element '%s'.", $matches[2]), HtmlFormException::INVALID_MARKUP);
                        }

                        $attributes = array_change_key_case($attributes, CASE_LOWER);

                        if (isset($attributes['name'])) {
                            throw new HtmlFormException(sprintf("Attribute 'name' is not allowed with element '%s'.", $matches[2]), HtmlFormException::INVALID_MARKUP);
                        }

                    }

                    // insert rendered element or label

                    if (is_array($this->elements[$matches[2]])) {

                        if (!isset($this->formElementIndexes[$matches[2]])) {
                            $this->formElementIndexes[$matches[2]] = 0;
                        }

                        if ('label' === strtolower($matches[1])) {

                            // insert label, array index does not advance

                            $e = $this->elements[$matches[2]][$this->formElementIndexes[$matches[2]]]->getLabel();

                        } else {

                            // insert element, advance array index

                            $e = $this->elements[$matches[2]][$this->formElementIndexes[$matches[2]]++];

                        }

                    } else {

                        // insert element

                        $e = $this->elements[$matches[2]];

                        if ('label' === strtolower($matches[1])) {

                            // insert label

                            $e = $e->getLabel();

                        }
                    }

                    if($e) {

                        if (isset($attributes)) {
                            $e->setAttributes($attributes);
                        }

                        return $e->render();
                    }

                }
			},

			$this->template
		);
		
		return $this;

	}