1

I'm trying to make custom lookup field with JS Link processing its templates, but I'm not guru in JS so ... nothing works :)

Here is what I've got now:

    // ------------------------------------------
// FUNCTION : GetFieldControlPrefix
// ------------------------------------------

function GetFieldControlPrefix(ctx) {
    return ctx.CurrentFieldSchema.Name + '_' + ctx.CurrentFieldSchema.Id;
};

// ------------------------------------------
// OBJ: AdvLookupQueryArray
// ------------------------------------------
AdvLookupQueryArray = [];

// ------------------------------------------
// FUNCTION : AdvLookupField_RegisterTemplates
// ------------------------------------------
function AdvLookupField_RegisterTemplates ()
{
    var AdvLookupContext = {};
    AdvLookupContext.Templates = {};
    AdvLookupContext.Templates.Fields = {
        "AdvLookupField":
        {
            "EditForm": AdvLookupField_Template_Edit
        }
    };
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(AdvLookupContext);
};

// ------------------------------------------
// FUNCTION : AdvLookupField_Template_Edit
// ------------------------------------------
function AdvLookupField_Template_Edit(ctx)
{
     var sHtml = ""; // output html string

    // write select box
    sHtml += "<select id='" + GetFieldControlPrefix(ctx) + "_SelectBox" + "' ></select>";

    // run query obejct
    AdvLookupQueryArray[AdvLookupQueryArray.length] = new AdvLookupQuery(GetFieldControlPrefix(ctx));

    return sHtml;
};

// ------------------------------------------
// AdvLookupQuery.
// ------------------------------------------
function AdvLookupQuery(ctrlPrefix) {

    self = this;

    // QueryResults
    self.QueryResults = null;

    // ControlPrefix
    self.ControlPrefix = ctrlPrefix;

    // ------------------------------------------
    // FUNCTION : AdvLookupQuery.StartQuery
    // ------------------------------------------
    AdvLookupQuery.prototype.StartQuery = function () {
        // Load context
        var spContext = new SP.ClientContext.get_current();

        // Get lookup list
        var spLookupList = spContext.get_web().get_lists().getByTitle("AdvLookupTest2");

        // Prepare query
        var spCamlQuery = new SP.CamlQuery();
        var spViewXML = '<View><RowLimit>999</RowLimit></View>';
        spCamlQuery.set_viewXml(spViewXML);

        // Prepare result items
        self.QueryResults = spLookupList.getItems(spCamlQuery);

        // Execute query on list
        spContext.load(self.QueryResults);//, "Include(Id, DisplayName, Title)");
        spContext.executeQueryAsync(Function.createDelegate(self, self.onQuerySuccess), Function.createDelegate(self, self.onQueryFail));
    };

    // ------------------------------------------
    // FUNCTION : AdvLookupQuery.onQuerySucces
    // ------------------------------------------
    AdvLookupQuery.prototype.onQuerySuccess = function () {
        alert("OK for " + self.ControlPrefix);
    };

    // ------------------------------------------
    // FUNCTION : AdvLookupQuery.onQueryFail
    // ------------------------------------------
    AdvLookupQuery.prototype.onQueryFail = function (sender, args) {
        alert("fail for " + self.ControlPrefix + args.get_message() + '\n' + args.get_stackTrace());
    };

    // Start query
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', self.StartQuery);
};

//
ExecuteOrDelayUntilScriptLoaded(AdvLookupField_RegisterTemplates, "clienttemplates.js");

I've re-made whole code to be a bit more clear. Ok, so what it should do : 1. Every template call creates new instance of AdvLookupQuery with unique field id and puts it into array; 2. AdvLookupQuery should process async request and fill data into control.

At test page I see two instances of AdvLookupQuery ( I have two fields on test list ) , they have correct ControlPrefix, onQuerySucess called two times, but in alert it always shows ControlPrefix of last item and QueryResults are filled only on last AdvLookupQuery object.

If im using "this" instead of "self" I'm getting no result at all (no events are fired). This always points to window instead of query object.

What am I doing wrong?

1

Client Side Rendering templates in SharePoint 2013 are synchronous. If you need to pull data from somewhere you have to first render an empty control, and then fill it with data as soon as they arrive.

As I can see you already have almost all the pieces in place, except of actually processing the data after it arrives.

So on query success you should do something like this:

AdvLookupField.onQuerySuccess = function () {
    var enumerator = this.QueryResults.getEnumerator();
    var select = document.getElementById(this.SelectBoxId);

    while (enumerator.moveNext())
    {
        var item = enumerator.get_current();
        var option = document.createElement("option");
        option.text = item.get_item("Title");
        option.value = item.get_id();
        if (this.CurrentFieldValue_LookupId == item.get_id())
          option.selected = true;
        select.appendChild(option);
    }
}

As you see you should also pass CurrentFieldValue_Id, so that your Template_Edit function will also change slightly:

AdvLookupField.CurrentFieldValue_LookupId = -1;
// ...
AdvLookupField.Template_Edit = function(ctx) {
   // ...

   // here I assume that the AdvLookupField field is of type Lookup
   this.CurrentFieldValue_LookupId = SPClientTemplates.Utility.ParseLookupValue(ctx.CurrentFieldValue).LookupId;

   // ...
}
  • But problem is not actually on getting data, its on onQuerySuccess or onQueryFail are never fired :( So during template processing im creating new AdvLookupField, says to it what controll it is assigned with so during async responce it fill controll with data, but no luck :( – IanRy Sep 16 '13 at 9:58
  • In this case you should first of all clearly explain that in your question. – Andrey Markeev Sep 16 '13 at 15:26
  • Explained now :) – IanRy Sep 18 '13 at 10:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.