6

There are tasks I'd like to do in Anguilla. I can see the Anguilla objects in the browser's JS console, but there are thousands of potential methods, and without docs, it's 'needle in a haystack' potluck experimentation.

I've seen auto-docs, but these are skeleton, and not enough to work out how to achieve tasks like :

  • search for a component by it's name
  • upload files to a multimedia component

thanks for any help you may offer

1
  • 6
    I see this has been flagged as off-topic. I disagree. Commented Apr 29, 2016 at 11:17

2 Answers 2

4

As far as I can see, there is no "meaningful API documentation" that I can find either. There are, however, various tutorials online on putting together GUI extensions, for example:

Validating content on save: http://www.curlette.com/?p=913

Various useful snippets: https://github.com/TridionPractice/tridion-practice/wiki/AnguillaSnippets

Bear in mind that the CME offers functionality for both of your "How do I?" questions, so unless you're extending what the GUI does or making some kind of bookmarklet, it is likely that either the Event System or Core Service API might be a better fit.

Please bear in mind I've come to this answer by fiddling, so it may well not be "best practice"!

Working in the browser console:

Search for a component by it's name

You need an object to search, and to load that object in order to gain access to its properties. This seems a common theme in Anguilla. So, let's say you want to search a publication:

var publication = $tcm.getItem(publicationId);

If you now type publication.getSearchList you'll get the getSearchList function returned. You can see that it is a function with four parameters, the first of which is a Tridion.ContentManager.ListSearchFilter. This info is also in the "auto-docs", whre the other parameters are detailed.

For ListSearchFilter you will see that it has properties columns, conditions, constructor, prototype. There is no useful information about what "conditions" is, but a little further digging and watching the network panel in the browser console suggests it's pretty much a clone of SearchQueryData in the Core Service API.

var filter = {conditions: {searchIn: publicationId, searchQuery: "some search", recursive: true}};
var results = publication.getSearchList(filter);

You have to load the results:

results.load();

You can then work with the results, so results.getCount() gets you a count of the results, results.getItems() gets you an array of the results. What is returned is just stub data, so you may need to load individual results if you need more than that data.

Upload files to a Multimedia Component

Firstly, remember that any action involving files on the user's machine must be initiated by the user selecting a file and must involve a click. Browser security rules. With that in mind, remember there is "New Multimedia Component" and "Upload Multimedia Component" in the GUI already, and you can already load and save files when modifying Multimedia Components ... and attach Events to them.

Like the Core Service API, when you upload a file, it gets uploaded to a temporary location on the server. The request you make to create or modify a MM Component has to reference that location. If you watch the upload activity in the browser console, you can see that it posts to FileUpload.aspx, and if you look at what it returns, you get an HTML document with the information you need.

Making the assumption that you want to make your own upload interface, then you could do an Ajax POST to FileUpload.aspx, grab the data returned and then use that to save or create a MM Component. Here's a stub for an upload form; has to be run in the console (or a bookmarklet) from within Tridion:

var formWindow = window.open();

var formDocument = formWindow.document;
var formBody = formDocument.body;

var form = formDocument.createElement("form");
var input = formDocument.createElement("input");

input.setAttribute("name", "LoadFromDisk_upload_file");
input.setAttribute("type", "file");
input.setAttribute("id", "uploader");

form.setAttribute("action", location.protocol + "//" + location.host + "/WebUI/Core/Controls/UploadControl/FileUpload.aspx");
form.setAttribute("enctype", "multipart/form-data");

form.appendChild(input);
formBody.appendChild(form);

var uploader = formDocument.getElementById("uploader");

If you attach an event to uploader, then you can upload a file when the field changes. Note that it must be via a File input and done by the user (otherwise anyone could upload passwords.txt from your desktop, not that anyone I know has one of those!).

var nameOnServer = "";
var nameOnClient = "";

uploader.onchange = function() {
    var data = new FormData();
    data.append(uploader.getAttribute("name"), uploader.files[0]);

    var xhr = new XMLHttpRequest();
    xhr.open("POST", location.protocol + "//" + location.host + "/WebUI/Core/Controls/UploadControl/FileUpload.aspx", false);
    xhr.onreadystatechange = function(e) {
        if(xhr.readyState == XMLHttpRequest.DONE) {
            console.log("Uploaded");
            response = xhr.response;
            var parser = new DOMParser();
            var responseHTML = parser.parseFromString(response, "text/html");
            nameOnServer = responseHTML.getElementById("nameOnServer").value;
            nameOnClient= responseHTML.getElementById("nameOnClient").value;
            //Do stuff
        }
    }
    xhr.send(data);
}

Once you have the name on the server, you can upload the file. Clearly you should only call this when you have the data you need, i.e. from within the readystatechange handler.

If it's a new Component, you can create a default MM Component like so:

var newItem = $tcm.createNewItem($const.ItemType.COMPONENT); //or "tcm:16"

newItem.setOrganizationalItem("someFolderId");
newItem.addEventListener("idchange", function() { newItem.checkIn(); }); //Check in the component when it's created
newItem.createFromFile(nameOnServer, nameOnClient, false);

If you need to create a new MM Component with a specific Schema, then it'll be different and you'll need to set Metadata XML, Schema type, etc.

If it's an existing Component, then you don't create it from a file, you set the uploaded MM filename:

var existingItem = $tcm.getItem("someComponentId");

existingItem.addEventListener("load", function(e) {
    existingItem.removeEventListener(e.type, arguments.callee); //"load" is called on CheckIn (event below) too, we only want it once!
    existingItem.setUploadedMultimediaFilename(nameOnServer);
    existingItem.save();
});

existingItem.addEventListener("save", function() { existingItem.checkIn(); });
existingItem.checkOut();

Though again I stress that Events and Core Services may be a better fit, depending on your requirements. In fact, whilst I've attempted to answer you question "How do I upload files to a Multimedia Component?", it may well be that it's better to have an Event on save, or, if it's a GUI extension, to extend the inbuilt functionality rather than trying to recreate it.

2

As far as I know, there is no documentation per se other than the "auto-docs' which you have found. You are correct to say that this documentation is often not as fully detailed as you may wish, perhaps because Anguilla is an "advanced" API.

The most obvious strategy is to UTSL. Most people implementing GUI extensions are pretty quickly knee-deep in the SDL javascript. While this may leave you feeling a little unloved, it's effective.

There are also plenty of sources of information in the community. Asking a good question here on tridion.stackexchange.com will probably result in you getting high quality help the same day. Obviously it's up to you to show in your question how far you've managed to get and where exactly you are stuck, but this too is a really effective strategy.

There are also plenty of on-line articles, blog posts etc. If you search, you'll find plenty. And of course, once you've solved something interesting or difficult yourself, feel free to give back with an article of your own. The rest of us will appreciate it.

Last but not least - if you can suggest ways in which the official documentation can be better, then do so. The documentation team at SDL are very receptive to constructive feedback and, in my experience, they are very keen to deliver excellent documentation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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