/** Lightweight client-side rendering template overrides.*/ namespace CSR { export interface UpdatedValueCallback { ( value , fieldSchema ? ) : void ; } /** Creates new overrides. Call .register() at the end.*/ export function override ( listTemplateType ? , baseViewId ? ) { return new csr ( listTemplateType , baseViewId ) . onPreRender ( hookFormContext ) . onPostRender ( fixCsrCustomLayout ) ; function hookFormContext ( ctx ) { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . EditForm || ctx . ControlMode == SPClientTemplates . ClientControlMode . NewForm ) { for ( var i = 0 ; i < ctx . ListSchema . Field . length ; i ++ ) { var fieldSchemaInForm = ctx . ListSchema . Field [ i ] ; if ( ! ctx . FormContextHook ) { ctx . FormContextHook = { } ; var oldRegisterGetValueCallback = ctx . FormContext . registerGetValueCallback ; ctx . FormContext . registerGetValueCallback = ( fieldName , callback ) => { ctx . FormContextHook [ fieldName ] . getValue = callback ; oldRegisterGetValueCallback ( fieldName , callback ) ; } ; var oldUpdateControlValue = ctx . FormContext . updateControlValue ; ctx . FormContext . updateControlValue = ( fieldName , value ) => { oldUpdateControlValue ( fieldName , value ) ; var hookedContext = ensureFormContextHookField ( ctx . FormContextHook , fieldName ) ; hookedContext . lastValue = value ; var updatedCallbacks = ctx . FormContextHook [ fieldName ] . updatedValueCallbacks ; for ( var i = 0 ; i < updatedCallbacks . length ; i ++ ) { updatedCallbacks [ i ] ( value , hookedContext . fieldSchema ) ; } } ; } ensureFormContextHookField ( ctx . FormContextHook , fieldSchemaInForm . Name ) . fieldSchema = fieldSchemaInForm ; } } } function fixCsrCustomLayout ( ctx ) { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . Invalid || ctx . ControlMode == SPClientTemplates . ClientControlMode . View ) { return ; } if ( ctx . ListSchema . Field . length > 1 ) { var wpq = ctx . FormUniqueId ; var webpart = $get ( 'WebPart' + wpq ) ; var forms = webpart . getElementsByClassName ( 'ms-formtable' ) ; if ( forms . length > 0 ) { var placeholder = $get ( wpq + 'ClientFormTopContainer' ) ; var fragment = document . createDocumentFragment ( ) ; for ( var i = 0 ; i < placeholder . children . length ; i ++ ) { fragment . appendChild ( placeholder . children . item ( i ) ) ; } var form = forms . item ( 0 ) ; form . parentNode . replaceChild ( fragment , form ) ; } var old = ctx . CurrentItem ; ctx . CurrentItem = ctx . ListData . Items [ 0 ] ; var fields = ctx . ListSchema . Field ; for ( var j = 0 ; j < fields . length ; j ++ ) { var field = fields [ j ] ; var pHolderId = wpq + ctx . FormContext . listAttributes . Id + field . Name ; var span = $get ( pHolderId ) ; if ( span ) { span . outerHTML = ctx . RenderFieldByName ( ctx , field . Name ) ; } } ctx . CurrentItem = old ; } } } export function getFieldValue ( ctx , fieldName ) { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . EditForm || ctx . ControlMode == SPClientTemplates . ClientControlMode . NewForm ) { var contextWithHook = < IFormRenderContexWithHook > ctx ; if ( contextWithHook . FormContextHook && contextWithHook . FormContextHook [ fieldName ] && contextWithHook . FormContextHook [ fieldName ] . getValue ) { return contextWithHook . FormContextHook [ fieldName ] . getValue ( ) ; } } return null ; } export function getFieldSchema ( ctx , fieldName ) { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . EditForm || ctx . ControlMode == SPClientTemplates . ClientControlMode . NewForm ) { var contextWithHook = < IFormRenderContexWithHook > ctx ; if ( contextWithHook . FormContextHook && contextWithHook . FormContextHook [ fieldName ] ) { return contextWithHook . FormContextHook [ fieldName ] . fieldSchema ; } } return null ; } export function addUpdatedValueCallback ( ctx , fieldName , callback ) { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . EditForm || ctx . ControlMode == SPClientTemplates . ClientControlMode . NewForm ) { var contextWithHook = < IFormRenderContexWithHook > ctx ; if ( contextWithHook . FormContextHook ) { var f = ensureFormContextHookField ( contextWithHook . FormContextHook , fieldName ) ; var callbacks = f . updatedValueCallbacks ; if ( callbacks . indexOf ( callback ) == - 1 ) { callbacks . push ( callback ) ; if ( f . lastValue ) { callback ( f . lastValue , f . fieldSchema ) ; } } } } } export function removeUpdatedValueCallback ( ctx , fieldName , callback ) { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . EditForm || ctx . ControlMode == SPClientTemplates . ClientControlMode . NewForm ) { var contextWithHook = < IFormRenderContexWithHook > ctx ; if ( contextWithHook . FormContextHook ) { var callbacks = ensureFormContextHookField ( contextWithHook . FormContextHook , fieldName ) . updatedValueCallbacks ; var index = callbacks . indexOf ( callback ) ; if ( index != - 1 ) { callbacks . splice ( index , 1 ) ; } } } } export function getControl ( schema ) { var id = schema . Name + '_' + schema . Id + '_$' + schema . FieldType + 'Field' ; return < HTMLInputElement > $get ( id ) ; } export function getFieldTemplate ( field , mode ) { var ctx = { ListSchema : { Field : [ field ] } , FieldControlModes : { } } ; ctx . FieldControlModes [ field . Name ] = mode ; var templates = SPClientTemplates . TemplateManager . GetTemplates ( ctx ) ; return templates . Fields [ field . Name ] ; } class csr implements ICSR , SPClientTemplates . TemplateOverridesOptions { public Templates : SPClientTemplates . TemplateOverrides ; public OnPreRender : SPClientTemplates . RenderCallback [ ] ; public OnPostRender : SPClientTemplates . RenderCallback [ ] ; private IsRegistered : boolean ; constructor ( public ListTemplateType ? , public BaseViewID ? ) { this . Templates = { Fields : { } } ; this . OnPreRender = [ ] ; this . OnPostRender = [ ] ; this . IsRegistered = false ; } view ( template ) { this . Templates . View = template ; return this ; } item ( template ) { this . Templates . Item = template ; return this ; } header ( template ) { this . Templates . Header = template ; return this ; } body ( template ) { this . Templates . Body = template ; return this ; } footer ( template ) { this . Templates . Footer = template ; return this ; } fieldView ( fieldName , template ) { this . Templates . Fields [ fieldName ] = this . Templates . Fields [ fieldName ] || { } ; this . Templates . Fields [ fieldName ] . View = template ; return this ; } fieldDisplay ( fieldName , template ) { this . Templates . Fields [ fieldName ] = this . Templates . Fields [ fieldName ] || { } ; this . Templates . Fields [ fieldName ] . DisplayForm = template ; return this ; } fieldNew ( fieldName , template ) { this . Templates . Fields [ fieldName ] = this . Templates . Fields [ fieldName ] || { } ; this . Templates . Fields [ fieldName ] . NewForm = template ; return this ; } fieldEdit ( fieldName , template ) { this . Templates . Fields [ fieldName ] = this . Templates . Fields [ fieldName ] || { } ; this . Templates . Fields [ fieldName ] . EditForm = template ; return this ; } template ( name , template ) { this . Templates [ name ] = template ; return this ; } fieldTemplate ( fieldName , name , template ) { this . Templates . Fields [ fieldName ] = this . Templates . Fields [ fieldName ] || { } ; this . Templates . Fields [ fieldName ] [ name ] = template ; return this ; } onPreRender ( ... callbacks ) { for ( var i = 0 ; i < callbacks . length ; i ++ ) { this . OnPreRender . push ( callbacks [ i ] ) ; } return this ; } onPostRender ( ... callbacks ) { for ( var i = 0 ; i < callbacks . length ; i ++ ) { this . OnPostRender . push ( callbacks [ i ] ) ; } return this ; } onPreRenderField ( field , callback ) { return this . onPreRender ( ( ctx ) => { var ctxInView = < SPClientTemplates . RenderContext_InView > ctx ; var fields = ctxInView . ListSchema . Field ; if ( fields ) { for ( var i = 0 ; i < fields . length ; i ++ ) { if ( fields [ i ] . Name === field ) { callback ( fields [ i ] , ctx ) ; } } } } ) ; } onPostRenderField ( field , callback ) { return this . onPostRender ( ( ctx ) => { var ctxInView = < SPClientTemplates . RenderContext_InView > ctx ; var fields = ctxInView . ListSchema . Field ; if ( fields ) { for ( var i = 0 ; i < fields . length ; i ++ ) { if ( fields [ i ] . Name === field ) { callback ( fields [ i ] , ctx ) ; } } } } ) ; } makeReadOnly ( fieldName ) { return this . onPreRenderField ( fieldName , ( schema , ctx ) => { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . Invalid || ctx . ControlMode == SPClientTemplates . ClientControlMode . DisplayForm ) return ; ( < SPClientTemplates . FieldSchema_InForm > schema ) . ReadOnlyField = true ; ( < SPClientTemplates . FieldSchema_InView > schema ) . ReadOnly = "TRUE" ; if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . View ) { var ctxInView = < SPClientTemplates . RenderContext_InView > ctx ; if ( ctxInView . inGridMode ) { } } else { var ctxInForm = < SPClientTemplates . RenderContext_FieldInForm > ctx ; if ( schema . Type != 'User' && schema . Type != 'UserMulti' ) { var template = getFieldTemplate ( schema , SPClientTemplates . ClientControlMode . DisplayForm ) ; ctxInForm . Templates . Fields [ fieldName ] = template ; ctxInForm . FormContext . registerGetValueCallback ( fieldName , ( ) => ctxInForm . ListData . Items [ 0 ] [ fieldName ] ) ; } } } ) . onPostRenderField ( fieldName , ( schema , ctx ) => { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . EditForm || ctx . ControlMode == SPClientTemplates . ClientControlMode . NewForm ) { if ( schema . Type == 'User' || schema . Type == 'UserMulti' ) { SP . SOD . executeFunc ( 'clientpeoplepicker.js' , 'SPClientPeoplePicker' , ( ) => { var topSpanId = schema . Name + '_' + schema . Id + '_$ClientPeoplePicker' ; var retryCount = 10 ; var callback = ( ) => { var pp = SPClientPeoplePicker . SPClientPeoplePickerDict [ topSpanId ] ; if ( ! pp ) { if ( retryCount -- ) setTimeout ( callback , 1 ) ; } else { pp . SetEnabledState ( false ) ; pp . DeleteProcessedUser = function ( ) { } ; } } ; callback ( ) ; } ) ; } } } ) ; } makeHidden ( fieldName ) { return this . onPreRenderField ( fieldName , ( schema , ctx ) => { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . Invalid ) return ; ( < SPClientTemplates . FieldSchema_InForm > schema ) . Hidden = true ; if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . View ) { var ctxInView = < SPClientTemplates . RenderContext_InView > ctx ; if ( ctxInView . inGridMode ) { } else { ctxInView . ListSchema . Field . splice ( ctxInView . ListSchema . Field . indexOf ( schema ) , 1 ) ; } } else { var ctxInForm = < SPClientTemplates . RenderContext_Form > ctx ; var pHolderId = ctxInForm . FormUniqueId + ctxInForm . FormContext . listAttributes . Id + fieldName ; var placeholder = $get ( pHolderId ) ; var current = placeholder ; while ( current . tagName . toUpperCase ( ) !== "TR" ) { current = current . parentElement ; } var row = < HTMLTableRowElement > current ; row . style . display = 'none' ; } } ) ; } filteredLookup ( fieldName , camlFilter , listname ? , lookupField ? ) { return this . fieldEdit ( fieldName , SPFieldCascadedLookup_Edit ) . fieldNew ( fieldName , SPFieldCascadedLookup_Edit ) ; function SPFieldCascadedLookup_Edit ( rCtx ) { var parseRegex = /\{[^\}]+\}/g ; var dependencyExpressions = [ ] ; var result ; while ( ( result = parseRegex . exec ( camlFilter ) ) ) { dependencyExpressions . push ( stripBraces ( result [ 0 ] ) ) ; } var dependencyValues = { } ; var _dropdownElt ; var _myData ; if ( rCtx == null ) return '' ; _myData = SPClientTemplates . Utility . GetFormContextForCurrentField ( rCtx ) ; if ( _myData == null || _myData . fieldSchema == null ) return '' ; var _schema = < SPClientTemplates . FieldSchema_InForm_Lookup > _myData . fieldSchema ; var validators = new SPClientForms . ClientValidation . ValidatorSet ( ) ; validators . RegisterValidator ( new BooleanValueValidator ( ( ) => _optionsLoaded , "Wait until lookup values loaded and try again" ) ) ; if ( _myData . fieldSchema . Required ) { validators . RegisterValidator ( new SPClientForms . ClientValidation . RequiredValidator ( ) ) ; } _myData . registerClientValidator ( _myData . fieldName , validators ) ; var _dropdownId = _myData . fieldName + '_' + _myData . fieldSchema . Id + '_$LookupField' ; var _valueStr = _myData . fieldValue != null ? _myData . fieldValue : '' ; var _selectedValue = SPClientTemplates . Utility . ParseLookupValue ( _valueStr ) . LookupId ; var _noValueSelected = _selectedValue == 0 ; var _optionsLoaded = false ; var pendingLoads = 0 ; if ( _noValueSelected ) _valueStr = '' ; _myData . registerInitCallback ( _myData . fieldName , InitLookupControl ) ; _myData . registerFocusCallback ( _myData . fieldName , function ( ) { if ( _dropdownElt != null ) _dropdownElt . focus ( ) ; } ) ; _myData . registerValidationErrorCallback ( _myData . fieldName , function ( errorResult ) { SPFormControl_AppendValidationErrorMessage ( _dropdownId , errorResult ) ; } ) ; _myData . registerGetValueCallback ( _myData . fieldName , GetCurrentLookupValue ) ; _myData . updateControlValue ( _myData . fieldName , _valueStr ) ; return BuildLookupDropdownControl ( ) ; function InitLookupControl ( ) { _dropdownElt = < HTMLSelectElement > document . getElementById ( _dropdownId ) ; if ( _dropdownElt != null ) AddEvtHandler ( _dropdownElt , "onchange" , OnLookupValueChanged ) ; SP . SOD . executeFunc ( 'sp.js' , 'SP.ClientContext' , ( ) => { bindDependentControls ( dependencyExpressions ) ; loadOptions ( true ) ; } ) ; } function BuildLookupDropdownControl ( ) { var result = '<span dir="' + STSHtmlEncode ( _myData . fieldSchema . Direction ) + '">' ; result += '<select id="' + STSHtmlEncode ( _dropdownId ) + '" title="' + STSHtmlEncode ( _myData . fieldSchema . Title ) + '">' ; result += '</select><br/></span>' ; return result ; } function OnLookupValueChanged ( ) { if ( _optionsLoaded ) { if ( _dropdownElt != null ) { _myData . updateControlValue ( _myData . fieldName , GetCurrentLookupValue ( ) ) ; _selectedValue = parseInt ( _dropdownElt . value , 10 ) ; } } } function GetCurrentLookupValue ( ) { if ( _dropdownElt == null ) return '' ; return _dropdownElt . value == '0' || _dropdownElt . value == '' ? '' : _dropdownElt . value + ';#' + _dropdownElt . options [ _dropdownElt . selectedIndex ] . text ; } function stripBraces ( input ) { return input . substring ( 1 , input . length - 1 ) ; } function getDependencyValue ( expr , value , listId , expressionParts , callback ) { var isLookupValue = ! ! listId ; if ( isLookupValue ) { var lookup = SPClientTemplates . Utility . ParseLookupValue ( value ) ; if ( expressionParts . length == 1 && expressionParts [ 0 ] == 'Value' ) { value = lookup . LookupValue ; expressionParts . shift ( ) ; } else { value = lookup . LookupId . toString ( ) ; } } if ( expressionParts . length == 0 ) { dependencyValues [ expr ] = value ; callback ( ) ; } else { var ctx = SP . ClientContext . get_current ( ) ; var web = ctx . get_web ( ) ; var list = web . get_lists ( ) . getById ( listId ) ; var item = list . getItemById ( parseInt ( value , 10 ) ) ; var field = list . get_fields ( ) . getByInternalNameOrTitle ( expressionParts . shift ( ) ) ; ctx . load ( item ) ; ctx . load ( field ) ; ctx . executeQueryAsync ( ( o , e ) => { var value = item . get_item ( field . get_internalName ( ) ) ; if ( field . get_typeAsString ( ) == 'Lookup' ) { field = < SP . Field > ctx . castTo ( field , SP . FieldLookup ) ; var lookup = ( < SP . FieldLookupValue > value ) ; value = lookup . get_lookupId ( ) + ';#' + lookup . get_lookupValue ( ) ; listId = ( < SP . FieldLookup > field ) . get_lookupList ( ) ; } getDependencyValue ( expr , value , listId , expressionParts , callback ) ; } , ( o , args ) => { console . log ( args . get_message ( ) ) ; } ) ; } } function bindDependentControls ( dependencyExpressions ) { dependencyExpressions . forEach ( expr => { var exprParts = expr . split ( "." ) ; var field = exprParts . shift ( ) ; CSR . addUpdatedValueCallback ( rCtx , field , ( v , s ) => { getDependencyValue ( expr , v , ( < SPClientTemplates . FieldSchema_InForm_Lookup > s ) . LookupListId , exprParts . slice ( 0 ) , loadOptions ) ; } ) ; } ) ; } function loadOptions ( isFirstLoad ? ) { _optionsLoaded = false ; pendingLoads ++ ; var ctx = SP . ClientContext . get_current ( ) ; var web = ctx . get_web ( ) ; var listId = _schema . LookupListId ; var list = ! listname ? web . get_lists ( ) . getById ( listId ) : web . get_lists ( ) . getByTitle ( listname ) ; var query = new SP . CamlQuery ( ) ; var predicate = camlFilter . replace ( parseRegex , ( v , a ) => { var expr = stripBraces ( v ) ; return dependencyValues [ expr ] ? dependencyValues [ expr ] : '' ; } ) ; if ( predicate . substr ( 0 , 5 ) == '<View' ) { query . set_viewXml ( predicate ) ; } else { query . set_viewXml ( '<View Scope="RecursiveAll"><Query><Where>' + predicate + '</Where></Query> ' + '<ViewFields><FieldRef Name="ID" /><FieldRef Name="Title"/></ViewFields></View>' ) ; } var results = list . getItems ( query ) ; ctx . load ( results ) ; ctx . executeQueryAsync ( ( o , e ) => { var selected = false ; while ( _dropdownElt . options . length ) { _dropdownElt . options . remove ( 0 ) ; } if ( ! _schema . Required ) { var defaultOpt = new Option ( Strings . STS . L_LookupFieldNoneOption , '0' , selected , selected ) ; _dropdownElt . options . add ( defaultOpt ) ; selected = _selectedValue == 0 ; } var isEmptyList = true ; var enumerator = results . getEnumerator ( ) ; while ( enumerator . moveNext ( ) ) { var c = enumerator . get_current ( ) ; var id ; var text ; if ( ! lookupField ) { id = c . get_id ( ) ; text = c . get_item ( 'Title' ) ; } else { var value = < SP . FieldLookupValue > c . get_item ( lookupField ) ; id = value . get_lookupId ( ) ; text = value . get_lookupValue ( ) ; } var isSelected = _selectedValue == id ; if ( isSelected ) { selected = true ; } var opt = new Option ( text , id . toString ( ) , isSelected , isSelected ) ; _dropdownElt . options . add ( opt ) ; isEmptyList = false ; } pendingLoads -- ; _optionsLoaded = true ; if ( ! pendingLoads ) { if ( isFirstLoad ) { if ( _selectedValue == 0 && ! selected ) { _dropdownElt . selectedIndex = 0 ; OnLookupValueChanged ( ) ; } } else { if ( _selectedValue != 0 && ! selected ) { _dropdownElt . selectedIndex = 0 ; } OnLookupValueChanged ( ) ; } } } , ( o , args ) => { console . log ( args . get_message ( ) ) ; } ) ; } } } computedValue ( targetField , transform , ... sourceField ) { var dependentValues = { } ; return this . onPostRenderField ( targetField , ( schema , ctx ) => { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . EditForm || ctx . ControlMode == SPClientTemplates . ClientControlMode . NewForm ) { var targetControl = CSR . getControl ( schema ) ; sourceField . forEach ( ( field ) => { CSR . addUpdatedValueCallback ( ctx , field , v => { dependentValues [ field ] = v ; targetControl . value = transform . apply ( this , sourceField . map ( n => dependentValues [ n ] || '' ) ) ; } ) ; } ) ; } } ) ; } setInitialValue ( fieldName , value , ignoreNull ? ) { if ( value || ! ignoreNull ) { return this . onPreRenderField ( fieldName , ( schema , ctx ) => { ctx . ListData . Items [ 0 ] [ fieldName ] = value ; } ) ; } else { return this ; } } autofill ( fieldName , init ) { return this . fieldNew ( fieldName , SPFieldLookup_Autofill_Edit ) . fieldEdit ( fieldName , SPFieldLookup_Autofill_Edit ) ; function SPFieldLookup_Autofill_Edit ( rCtx ) { if ( rCtx == null ) return '' ; var _myData = SPClientTemplates . Utility . GetFormContextForCurrentField ( rCtx ) ; if ( _myData == null || _myData . fieldSchema == null ) return '' ; var _autoFillControl ; var _textInputElt ; var _textInputId = _myData . fieldName + '_' + _myData . fieldSchema . Id + '_$' + _myData . fieldSchema . Type + 'Field' ; var _autofillContainerId = _myData . fieldName + '_' + _myData . fieldSchema . Id + '_$AutoFill' ; var validators = new SPClientForms . ClientValidation . ValidatorSet ( ) ; if ( _myData . fieldSchema . Required ) { validators . RegisterValidator ( new SPClientForms . ClientValidation . RequiredValidator ( ) ) ; } _myData . registerClientValidator ( _myData . fieldName , validators ) ; _myData . registerInitCallback ( _myData . fieldName , initAutoFillControl ) ; _myData . registerFocusCallback ( _myData . fieldName , function ( ) { if ( _textInputElt != null ) _textInputElt . focus ( ) ; } ) ; _myData . registerValidationErrorCallback ( _myData . fieldName , function ( errorResult ) { SPFormControl_AppendValidationErrorMessage ( _textInputId , errorResult ) ; } ) ; _myData . registerGetValueCallback ( _myData . fieldName , ( ) => _myData . fieldValue ) ; _myData . updateControlValue ( _myData . fieldName , _myData . fieldValue ) ; return buildAutoFillControl ( ) ; function initAutoFillControl ( ) { _textInputElt = < HTMLInputElement > document . getElementById ( _textInputId ) ; SP . SOD . executeFunc ( "autofill.js" , "SPClientAutoFill" , ( ) => { _autoFillControl = new SPClientAutoFill ( _textInputId , _autofillContainerId , ( _ ) => callback ( ) ) ; var callback = init ( { renderContext : rCtx , fieldContext : _myData , autofill : _autoFillControl , control : _textInputElt } ) ; } ) ; } function buildAutoFillControl ( ) { var result = [ ] ; result . push ( '<div dir="' + STSHtmlEncode ( _myData . fieldSchema . Direction ) + '" style="position: relative;">' ) ; result . push ( '<input type="text" id="' + STSHtmlEncode ( _textInputId ) + '" title="' + STSHtmlEncode ( _myData . fieldSchema . Title ) + '"/>' ) ; result . push ( "<div class='sp-peoplepicker-autoFillContainer' id='" + STSHtmlEncode ( _autofillContainerId ) + "'></div>" ) ; result . push ( "</div>" ) ; return result . join ( "" ) ; } } } seachLookup ( fieldName ) { return this . autofill ( fieldName , ( ctx ) => { var _myData = ctx . fieldContext ; var _schema = < SPClientTemplates . FieldSchema_InForm_Lookup > _myData . fieldSchema ; if ( _myData . fieldSchema . Type != 'Lookup' ) { return null ; } var _valueStr = _myData . fieldValue != null ? _myData . fieldValue : '' ; var _selectedValue = SPClientTemplates . Utility . ParseLookupValue ( _valueStr ) ; var _noValueSelected = _selectedValue . LookupId == 0 ; ctx . control . value = _selectedValue . LookupValue ; $addHandler ( ctx . control , "blur" , _ => { if ( ctx . control . value == '' ) { _myData . fieldValue = '' ; _myData . updateControlValue ( fieldName , _myData . fieldValue ) ; } } ) ; if ( _noValueSelected ) _myData . fieldValue = '' ; var _autoFillControl = ctx . autofill ; _autoFillControl . AutoFillMinTextLength = 2 ; _autoFillControl . VisibleItemCount = 15 ; _autoFillControl . AutoFillTimeout = 500 ; return ( ) => { var value = ctx . control . value ; _autoFillControl . PopulateAutoFill ( [ AutoFillOptionBuilder . buildLoadingItem ( 'Please wait...' ) ] , onSelectItem ) ; SP . SOD . executeFunc ( "sp.search.js" , "Microsoft.SharePoint.Client.Search.Query" , ( ) => { var Search = Microsoft . SharePoint . Client . Search . Query ; var ctx = SP . ClientContext . get_current ( ) ; var query = new Search . KeywordQuery ( ctx ) ; query . set_rowLimit ( _autoFillControl . VisibleItemCount ) ; query . set_queryText ( 'contentclass:STS_ListItem ListID:{' + _schema . LookupListId + '} ' + value ) ; var selectProps = query . get_selectProperties ( ) ; selectProps . clear ( ) ; selectProps . add ( 'Title' ) ; selectProps . add ( 'ListItemId' ) ; var executor = new Search . SearchExecutor ( ctx ) ; var result = executor . executeQuery ( query ) ; ctx . executeQueryAsync ( ( ) => { var tableCollection = new Search . ResultTableCollection ( ) ; tableCollection . initPropertiesFromJson ( result . get_value ( ) ) ; var relevantResults = tableCollection . get_item ( 0 ) ; var rows = relevantResults . get_resultRows ( ) ; var items = [ ] ; for ( var i = 0 ; i < rows . length ; i ++ ) { items . push ( AutoFillOptionBuilder . buildOptionItem ( parseInt ( rows [ i ] [ "ListItemId" ] , 10 ) , rows [ i ] [ "Title" ] ) ) ; } items . push ( AutoFillOptionBuilder . buildSeparatorItem ( ) ) ; if ( relevantResults . get_totalRows ( ) == 0 ) items . push ( AutoFillOptionBuilder . buildFooterItem ( "No results. Please refine your query." ) ) ; else items . push ( AutoFillOptionBuilder . buildFooterItem ( "Showing " + rows . length + " of" + relevantResults . get_totalRows ( ) + " items!" ) ) ; _autoFillControl . PopulateAutoFill ( items , onSelectItem ) ; } , ( sender , args ) => { _autoFillControl . PopulateAutoFill ( [ AutoFillOptionBuilder . buildFooterItem ( "Error executing query/ See log for details." ) ] , onSelectItem ) ; console . log ( args . get_message ( ) ) ; } ) ; } ) ; } ; function onSelectItem ( targetInputId , item ) { var targetElement = ctx . control ; targetElement . value = item [ SPClientAutoFill . DisplayTextProperty ] ; _selectedValue . LookupId = item [ SPClientAutoFill . KeyProperty ] ; _selectedValue . LookupValue = item [ SPClientAutoFill . DisplayTextProperty ] ; _myData . fieldValue = item [ SPClientAutoFill . KeyProperty ] + ';#' + item [ SPClientAutoFill . TitleTextProperty ] ; _myData . updateControlValue ( _myData . fieldSchema . Name , _myData . fieldValue ) ; } } ) ; } lookupAddNew ( fieldName , prompt , showDialog ? , contentTypeId ? ) { return this . onPostRenderField ( fieldName , ( schema , ctx ) => { if ( ctx . ControlMode == SPClientTemplates . ClientControlMode . EditForm || ctx . ControlMode == SPClientTemplates . ClientControlMode . NewForm ) var control = CSR . getControl ( schema ) ; if ( control ) { var weburl = _spPageContextInfo . webServerRelativeUrl ; if ( weburl [ weburl . length - 1 ] == '/' ) { weburl = weburl . substring ( 0 , weburl . length - 1 ) ; } var newFormUrl = weburl + '/_layouts/listform.aspx/listform.aspx?PageType=8' + "&ListId=" + encodeURIComponent ( '{' + schema . LookupListId + '}' ) ; if ( contentTypeId ) { newFormUrl += '&ContentTypeId=' + contentTypeId ; } var link = document . createElement ( 'a' ) ; link . href = "javascript:NewItem2(event, \'" + newFormUrl + "&Source=" + encodeURIComponent ( document . location . href ) + "')" ; link . textContent = prompt ; if ( control . nextElementSibling ) { control . parentElement . insertBefore ( link , control . nextElementSibling ) ; } else { control . parentElement . appendChild ( link ) ; } if ( showDialog ) { $addHandler ( link , "click" , ( e ) => { SP . SOD . executeFunc ( 'sp.ui.dialog.js' , 'SP.UI.ModalDialog.ShowPopupDialog' , ( ) => { SP . UI . ModalDialog . ShowPopupDialog ( newFormUrl ) ; } ) ; e . stopPropagation ( ) ; e . preventDefault ( ) ; } ) ; } } } ) ; } register ( ) { if ( ! this . IsRegistered ) { SPClientTemplates . TemplateManager . RegisterTemplateOverrides ( this ) ; this . IsRegistered = true ; } } } export class AutoFillOptionBuilder { static buildFooterItem ( title ) { var item = { } ; item [ SPClientAutoFill . DisplayTextProperty ] = title ; item [ SPClientAutoFill . MenuOptionTypeProperty ] = SPClientAutoFill . MenuOptionType . Footer ; return item ; } static buildOptionItem ( id , title , displayText ? , subDisplayText ? ) { var item = { } ; item [ SPClientAutoFill . KeyProperty ] = id ; item [ SPClientAutoFill . DisplayTextProperty ] = displayText || title ; item [ SPClientAutoFill . SubDisplayTextProperty ] = subDisplayText ; item [ SPClientAutoFill . TitleTextProperty ] = title ; item [ SPClientAutoFill . MenuOptionTypeProperty ] = SPClientAutoFill . MenuOptionType . Option ; return item ; } static buildSeparatorItem ( ) { var item = { } ; item [ SPClientAutoFill . MenuOptionTypeProperty ] = SPClientAutoFill . MenuOptionType . Separator ; return item ; } static buildLoadingItem ( title ) { var item = { } ; item [ SPClientAutoFill . MenuOptionTypeProperty ] = SPClientAutoFill . MenuOptionType . Loading ; item [ SPClientAutoFill . DisplayTextProperty ] = title ; return item ; } } /** Lightweight client-side rendering template overrides.*/ export interface ICSR { param name param template template ( name , template ) : ICSR ; param name param template template ( name , template ) : ICSR ; param name param name param template fieldTemplate ( field , name , template ) : ICSR ; param name param name param template fieldTemplate ( field , name , template ) : ICSR ; param callbacks onPreRender ( ... callbacks ) : ICSR ; param callbacks onPostRender ( ... callbacks ) : ICSR ; param fieldName param callbacks onPreRenderField ( field , callback ) : ICSR ; param fieldName param callbacks onPostRenderField ( field , callback ) : ICSR ; /** Registers overrides in client-side templating engine.*/ register ( ) : void ; param template view ( template ) : ICSR ; param template view ( template ) : ICSR ; view ( template ) : ICSR ; param template item ( template ) : ICSR ; param template item ( template ) : ICSR ; item ( template ) : ICSR ; param template header ( template ) : ICSR ; param template header ( template ) : ICSR ; param template body ( template ) : ICSR ; param template body ( template ) : ICSR ; param template footer ( template ) : ICSR ; param template footer ( template ) : ICSR ; param fieldName param template fieldView ( fieldName , template ) : ICSR ; param fieldName param template fieldView ( fieldName , template ) : ICSR ; param fieldName param template fieldDisplay ( fieldName , template ) : ICSR ; param fieldName param template fieldDisplay ( fieldName , template ) : ICSR ; param fieldName param template fieldEdit ( fieldName , template ) : ICSR ; param fieldName param template fieldEdit ( fieldName , template ) : ICSR ; param fieldName param template fieldNew ( fieldName , template ) : ICSR ; param fieldName param template fieldNew ( fieldName , template ) : ICSR ; param fieldName param value setInitialValue ( fieldName , value ) : ICSR ; param fieldName makeHidden ( fieldName ) : ICSR ; param fieldName makeReadOnly ( fieldName ) : ICSR ; param fieldName param camlFilter filteredLookup ( fieldName , camlFilter , listname ? , lookupField ? ) : ICSR ; param targetField param transform param sourceField computedValue ( targetField , transform , ... sourceField ) : ICSR ; param fieldName param ctx autofill ( fieldName , init ) : ICSR ; param fieldName seachLookup ( fieldName ) : ICSR ; param fieldName param prompt param contentTypeID lookupAddNew ( fieldName , prompt , showDialog ? , contentTypeId ? ) : ICSR ; } export interface IAutoFillFieldContext { renderContext : SPClientTemplates . RenderContext_FieldInForm ; fieldContext : SPClientTemplates . ClientFormContext ; autofill : SPClientAutoFill ; control : HTMLInputElement ; } interface IFormRenderContexWithHook extends SPClientTemplates . RenderContext_FieldInForm { FormContextHook : IFormContextHook ; } interface IFormContextHook { [ fieldName ] : IFormContextHookField ; } interface IFormContextHookField { fieldSchema ? : SPClientTemplates . FieldSchema_InForm ; lastValue ? : any ; getValue ? : ( ) => any ; updatedValueCallbacks : UpdatedValueCallback [ ] ; } function ensureFormContextHookField ( hook , fieldName ) { return hook [ fieldName ] = hook [ fieldName ] || { updatedValueCallbacks : [ ] } ; } class BooleanValueValidator implements SPClientForms . ClientValidation . IValidator { constructor ( public valueGetter , public validationMessage ) { } Validate ( value ) { return new SPClientForms . ClientValidation . ValidationResult ( ! this . valueGetter ( ) , this . validationMessage ) ; } } } if ( typeof SP == 'object' && SP && typeof SP . SOD == 'object' && SP . SOD ) { SP . SOD . notifyScriptLoadedAndExecuteWaitingJobs ( "sp-ts-csr.ts" ) ; }